From 4adb8cc1cbd87673bf3fcbac5caeab6fbd24fe44 Mon Sep 17 00:00:00 2001 From: Quentin Sabah Date: Fri, 6 Oct 2023 20:29:53 +0200 Subject: [PATCH] Introduce binary `+` symbol concatenation --- src/FunctorOps.cpp | 3 ++ src/FunctorOps.h | 1 + src/interpreter/Engine.cpp | 8 +++++ src/synthesiser/Synthesiser.cpp | 33 +++++++++++++++++-- tests/evaluation/CMakeLists.txt | 1 + tests/evaluation/symbol_operations/Add.csv | 9 +++++ .../symbol_operations/symbol_operations.dl | 23 +++++++++++++ .../symbol_operations/symbol_operations.err | 0 .../symbol_operations/symbol_operations.out | 0 9 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/evaluation/symbol_operations/Add.csv create mode 100644 tests/evaluation/symbol_operations/symbol_operations.dl create mode 100644 tests/evaluation/symbol_operations/symbol_operations.err create mode 100644 tests/evaluation/symbol_operations/symbol_operations.out diff --git a/src/FunctorOps.cpp b/src/FunctorOps.cpp index 178dcd89782..2da099c989e 100644 --- a/src/FunctorOps.cpp +++ b/src/FunctorOps.cpp @@ -48,6 +48,7 @@ char const* functorOpNameLegacy(FunctorOp op) { /** Binary Functor Operators */ case FunctorOp::ADD: case FunctorOp::FADD: + case FunctorOp::SSADD: case FunctorOp::UADD: return "+"; case FunctorOp::SUB: case FunctorOp::USUB: @@ -223,6 +224,8 @@ const std::vector FUNCTOR_INTRINSICS = { VARIADIC(CAT, Symbol), OP_1(STRLEN, Symbol, Signed), OP_3(SUBSTR, Symbol, Signed, Signed, Symbol, false), + + {functorOpNameSymbol(FOp::SSADD), {TAttr::Symbol, TAttr::Symbol}, TAttr::Symbol, FOp::SSADD, false, false}, }; template diff --git a/src/FunctorOps.h b/src/FunctorOps.h index 2ad98950a99..6a831715ced 100644 --- a/src/FunctorOps.h +++ b/src/FunctorOps.h @@ -101,6 +101,7 @@ enum class FunctorOp { FMIN, // min of two floats SMAX, // max of two symbols SMIN, // min of two symbols + SSADD, // string-string concatenation // Produces values within a numeric range. Format is `range(bgn, endExcl, step = 1)`. // e.g. `range(0, 5)` produces the sequence `0, 1, 2, 3, 4`. diff --git a/src/interpreter/Engine.cpp b/src/interpreter/Engine.cpp index 69c6b09dcae..521f7f9fc8e 100644 --- a/src/interpreter/Engine.cpp +++ b/src/interpreter/Engine.cpp @@ -784,6 +784,14 @@ RamDomain Engine::execute(const Node* node, Context& ctxt) { case FunctorOp::URANGE: case FunctorOp::FRANGE: fatal("ICE: functor `%s` must map onto `NestedIntrinsicOperator`", cur.getOperator()); + + case FunctorOp::SSADD: { + auto sleft = execute(shadow.getChild(0), ctxt); + auto sright = execute(shadow.getChild(1), ctxt); + const std::string& strleft = getSymbolTable().decode(sleft); + const std::string& strright = getSymbolTable().decode(sright); + return getSymbolTable().encode(strleft + strright); + } } {UNREACHABLE_BAD_CASE_ANALYSIS} diff --git a/src/synthesiser/Synthesiser.cpp b/src/synthesiser/Synthesiser.cpp index fdc6c254f39..82165ffd741 100644 --- a/src/synthesiser/Synthesiser.cpp +++ b/src/synthesiser/Synthesiser.cpp @@ -1864,7 +1864,7 @@ void Synthesiser::emitCode(std::ostream& out, const Statement& stmt) { // strings case BinaryConstraintOp::MATCH: { - if (const StringConstant* str = dynamic_cast(&rel.getLHS()); str) { + if (const StringConstant* str = as(&rel.getLHS()); str) { const auto& regex = synthesiser.compileRegex(str->getConstant()); if (regex) { out << "std::regex_match(symTable.decode("; @@ -1884,7 +1884,7 @@ void Synthesiser::emitCode(std::ostream& out, const Statement& stmt) { break; } case BinaryConstraintOp::NOT_MATCH: { - if (const StringConstant* str = dynamic_cast(&rel.getLHS()); str) { + if (const StringConstant* str = as(&rel.getLHS()); str) { const auto& regex = synthesiser.compileRegex(str->getConstant()); if (regex) { out << "!std::regex_match(symTable.decode("; @@ -2313,6 +2313,35 @@ void Synthesiser::emitCode(std::ostream& out, const Statement& stmt) { case FunctorOp::URANGE: case FunctorOp::FRANGE: fatal("ICE: functor `%s` must map onto `NestedIntrinsicOperator`", op.getOperator()); + + case FunctorOp::SSADD: { + const StringConstant* lstr = as(args[0]); + const StringConstant* rstr = as(args[1]); + if (lstr && rstr) { + out << "RamSigned(" + << synthesiser.convertSymbol2Idx(lstr->getConstant() + rstr->getConstant()) << ")"; + } else { + out << "symTable.encode("; + if (lstr) { + out << "R\"_(" << lstr->getConstant() << ")_\""; + } else { + out << "symTable.decode("; + dispatch(*args[0], out); + out << ")"; + } + out << " + "; + if (rstr) { + out << "R\"_(" << rstr->getConstant() << ")_\""; + } else { + out << "symTable.decode("; + dispatch(*args[1], out); + out << ")"; + } + out << ")"; + } + break; + } + } PRINT_END_COMMENT(out); diff --git a/tests/evaluation/CMakeLists.txt b/tests/evaluation/CMakeLists.txt index b55517a4d05..63aa0b5a078 100644 --- a/tests/evaluation/CMakeLists.txt +++ b/tests/evaluation/CMakeLists.txt @@ -161,6 +161,7 @@ positive_test(subtype2) positive_test(subtype) positive_test(sum-aggregate) positive_test(sum-aggregate2) +positive_test(symbol_operations) positive_test(term) positive_test(unpacking) positive_test(unsigned_operations) diff --git a/tests/evaluation/symbol_operations/Add.csv b/tests/evaluation/symbol_operations/Add.csv new file mode 100644 index 00000000000..3c250ab4c18 --- /dev/null +++ b/tests/evaluation/symbol_operations/Add.csv @@ -0,0 +1,9 @@ +pre--post +pre-(a) +pre-(b) +(a)-post +(b)-post +(b)(a)(a) +(a)(b)(b) +one:1, pi:3.140000 + diff --git a/tests/evaluation/symbol_operations/symbol_operations.dl b/tests/evaluation/symbol_operations/symbol_operations.dl new file mode 100644 index 00000000000..345dd7ddf01 --- /dev/null +++ b/tests/evaluation/symbol_operations/symbol_operations.dl @@ -0,0 +1,23 @@ +// Souffle - A Datalog Compiler +// Copyright (c) 2023, The Souffle Developers. All rights reserved +// Licensed under the Universal Permissive License v 1.0 as shown at: +// - https://opensource.org/licenses/UPL +// - /licenses/SOUFFLE-UPL.txt + +.decl Add(s:symbol) +Add("pre-" + "-post"). +Add("pre-" + s) :- some_symbol(s). +Add(s + "-post") :- some_symbol(s). +Add(s1 + s2 + s3) :- + some_symbol(s1), + some_symbol(s2), + some_symbol(s3), + s1 != s2, + s1 != s3. +Add("one:" + to_string(1) + ", pi:" + to_string(3.14) + "\n"). + +.decl some_symbol(s:symbol) +some_symbol("(a)"). +some_symbol("(b)"). + +.output Add() diff --git a/tests/evaluation/symbol_operations/symbol_operations.err b/tests/evaluation/symbol_operations/symbol_operations.err new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/evaluation/symbol_operations/symbol_operations.out b/tests/evaluation/symbol_operations/symbol_operations.out new file mode 100644 index 00000000000..e69de29bb2d