Skip to content

Commit d6a6d8b

Browse files
anutosh491Thirumalai-Shaktivelubaidskcertik
authored
Intial Implementation for SymbolicExpression ttype (#1846)
Co-authored-by: Thirumalai-Shaktivel <[email protected]> Co-authored-by: Shaikh Ubaid <[email protected]> Co-authored-by: Ondřej Čertík <[email protected]>
1 parent d0b957d commit d6a6d8b

File tree

14 files changed

+370
-25
lines changed

14 files changed

+370
-25
lines changed

.github/workflows/CI.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,47 @@ jobs:
333333
run: |
334334
cd integration_tests
335335
./run_tests.py -b cpython_py c_py
336+
337+
sympy:
338+
name: Run SymPy tests
339+
runs-on: ubuntu-latest
340+
steps:
341+
- uses: actions/checkout@v3
342+
with:
343+
fetch-depth: 0
344+
345+
- uses: mamba-org/setup-micromamba@v1
346+
with:
347+
environment-file: ci/environment.yml
348+
create-args: >-
349+
python=3.10
350+
bison=3.4
351+
symengine=0.9.0
352+
sympy=1.11.1
353+
354+
- uses: hendrikmuhs/ccache-action@main
355+
with:
356+
key: ${{ github.job }}-${{ matrix.os }}
357+
358+
- name: Build
359+
shell: bash -l {0}
360+
run: |
361+
./build0.sh
362+
cmake . -G"Unix Makefiles" \
363+
-DCMAKE_BUILD_TYPE=Debug \
364+
-DWITH_LLVM=yes \
365+
-DLPYTHON_BUILD_ALL=yes \
366+
-DWITH_STACKTRACE=no \
367+
-DWITH_RUNTIME_STACKTRACE=no \
368+
-DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
369+
-DCMAKE_INSTALL_PREFIX=`pwd`/inst \
370+
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
371+
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
372+
373+
cmake --build . -j16 --target install
374+
375+
- name: Test
376+
shell: bash -l {0}
377+
run: |
378+
cd integration_tests
379+
./run_tests.py -b c_sym cpython_sym

integration_tests/CMakeLists.txt

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,31 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_ENABLE_CPYTHON RUN
140140
if (${fail})
141141
set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
142142
endif()
143-
elseif((KIND STREQUAL "cpython") OR (KIND STREQUAL "cpython_py"))
143+
elseif(KIND STREQUAL "c_sym")
144+
add_custom_command(
145+
OUTPUT ${name}.c
146+
COMMAND ${LPYTHON} ${extra_args} --show-c
147+
${CMAKE_CURRENT_SOURCE_DIR}/${file_name}.py > ${name}.c
148+
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file_name}.py
149+
VERBATIM)
150+
add_executable(${name} ${name}.c ${extra_files})
151+
target_include_directories(${name} PRIVATE ${CMAKE_SOURCE_DIR}
152+
"${Python_INCLUDE_DIRS}/..")
153+
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C)
154+
if (APPLE)
155+
set(SYMENGINE_LIB "${Python_LIBRARY_DIRS}/libsymengine.dylib")
156+
else()
157+
set(SYMENGINE_LIB "${Python_LIBRARY_DIRS}/libsymengine.so")
158+
endif()
159+
target_link_libraries(${name} lpython_rtlib ${SYMENGINE_LIB})
160+
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
161+
if (labels)
162+
set_tests_properties(${name} PROPERTIES LABELS "${labels}")
163+
endif()
164+
if (${fail})
165+
set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
166+
endif()
167+
elseif((KIND STREQUAL "cpython") OR (KIND STREQUAL "cpython_py") OR (KIND STREQUAL "cpython_sym"))
144168
# CPython test
145169
if (extra_files)
146170
set(PY_MOD "${name}_mod")
@@ -267,7 +291,7 @@ macro(RUN)
267291
if ((NOT DISABLE_FAST) AND (NOT RUN_NOFAST))
268292
set(RUN_EXTRA_ARGS ${RUN_EXTRA_ARGS} --fast)
269293
set(RUN_NAME "${RUN_NAME}_FAST")
270-
list(REMOVE_ITEM RUN_LABELS cpython cpython_py) # remove cpython, cpython_py from --fast test
294+
list(REMOVE_ITEM RUN_LABELS cpython cpython_sym cpython_py) # remove cpython, cpython_sym, cpython_py from --fast test
271295
RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_ENABLE_CPYTHON RUN_EXTRAFILES RUN_EXTRA_ARGS)
272296
endif()
273297
endmacro(RUN)
@@ -552,6 +576,9 @@ RUN(NAME structs_24 LABELS cpython llvm c)
552576
RUN(NAME structs_25 LABELS cpython llvm c)
553577
RUN(NAME structs_26 LABELS cpython llvm c)
554578
RUN(NAME structs_27 LABELS cpython llvm c)
579+
580+
RUN(NAME symbolics_01 LABELS cpython_sym c_sym)
581+
555582
RUN(NAME sizeof_01 LABELS llvm c
556583
EXTRAFILES sizeof_01b.c)
557584
RUN(NAME sizeof_02 LABELS cpython llvm c)

integration_tests/run_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
# Initialization
88
DEFAULT_THREADS_TO_USE = 8 # default no of threads is 8
9-
SUPPORTED_BACKENDS = ['llvm', 'c', 'wasm', 'cpython', 'x86', 'wasm_x86', 'wasm_x64', 'c_py', 'cpython_py']
9+
SUPPORTED_BACKENDS = ['llvm', 'c', 'wasm', 'cpython', 'x86', 'wasm_x86', 'wasm_x64', 'c_py', 'cpython_py', 'c_sym', 'cpython_sym']
1010
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
1111
LPYTHON_PATH = f"{BASE_DIR}/../src/bin"
1212

integration_tests/symbolics_01.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from sympy import Symbol, pi
2+
from lpython import S
3+
4+
def main0():
5+
x: S = Symbol('x')
6+
y: S = Symbol('y')
7+
x = pi
8+
z: S = x + y
9+
print(z)
10+
11+
main0()

src/bin/lpython.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,14 @@ int link_executable(const std::vector<std::string> &infiles,
12441244
cmd += s + " ";
12451245
}
12461246
cmd += " -I " + rtlib_header_dir;
1247+
if (compiler_options.enable_symengine) {
1248+
cmd += " -I${CONDA_PREFIX}/include";
1249+
}
12471250
cmd += " -L" + base_path
12481251
+ " -Wl,-rpath," + base_path + " -l" + runtime_lib + " -lm";
1252+
if (compiler_options.enable_symengine) {
1253+
cmd += " -L$CONDA_PREFIX/lib -Wl,-rpath -Wl,$CONDA_PREFIX/lib -lsymengine";
1254+
}
12491255
if (compiler_options.enable_cpython) {
12501256
std::string py_version = "3.10";
12511257
std::string py_flags = R"(-I $CONDA_PREFIX/include/python)" + py_version + R"( -L$CONDA_PREFIX/lib -Wl,-rpath -Wl,$CONDA_PREFIX/lib -lpython)" + py_version + R"()";
@@ -1565,6 +1571,7 @@ int main(int argc, char *argv[])
15651571
app.add_flag("--get-rtl-dir", print_rtl_dir, "Print the path to the runtime library file");
15661572
app.add_flag("--verbose", compiler_options.verbose, "Print debugging statements");
15671573
app.add_flag("--enable-cpython", compiler_options.enable_cpython, "Enable CPython runtime");
1574+
app.add_flag("--enable-symengine", compiler_options.enable_symengine, "Enable Symengine runtime");
15681575
app.add_flag("--link-numpy", compiler_options.link_numpy, "Enable NumPy runtime (implies --enable-cpython)");
15691576

15701577
// LSP specific options

src/libasr/ASR.asdl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ ttype
383383
| Allocatable(ttype type)
384384
| Const(ttype type)
385385
| CPtr()
386+
| SymbolicExpression()
386387
| TypeParameter(identifier param)
387388
| Array(ttype type, dimension* dims)
388389
| FunctionType(ttype* arg_types, ttype? return_var_type,

src/libasr/asr_utils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ static inline std::string type_to_str(const ASR::ttype_t *t)
398398
ASR::TypeParameter_t* tp = ASR::down_cast<ASR::TypeParameter_t>(t);
399399
return tp->m_param;
400400
}
401+
case ASR::ttypeType::SymbolicExpression: {
402+
return "symbolic expression";
403+
}
401404
default : throw LCompilersException("Not implemented " + std::to_string(t->type) + ".");
402405
}
403406
}
@@ -1151,6 +1154,9 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco
11511154
return "Const[" + get_type_code(p->m_type, use_underscore_sep,
11521155
encode_dimensions_, set_dimensional_hint) + "]";
11531156
}
1157+
case ASR::ttypeType::SymbolicExpression: {
1158+
return "S";
1159+
}
11541160
default: {
11551161
throw LCompilersException("Type encoding not implemented for "
11561162
+ std::to_string(t->type));
@@ -1286,6 +1292,9 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
12861292
ASR::TypeParameter_t *p = ASR::down_cast<ASR::TypeParameter_t>(t);
12871293
return p->m_param;
12881294
}
1295+
case ASR::ttypeType::SymbolicExpression: {
1296+
return "S";
1297+
}
12891298
default : throw LCompilersException("Not implemented " + std::to_string(t->type));
12901299
}
12911300
}
@@ -1648,6 +1657,7 @@ inline int extract_dimensions_from_ttype(ASR::ttype_t *x,
16481657
n_dims = extract_dimensions_from_ttype(ASR::down_cast<ASR::Const_t>(x)->m_type, m_dims);
16491658
break;
16501659
}
1660+
case ASR::ttypeType::SymbolicExpression:
16511661
case ASR::ttypeType::Integer:
16521662
case ASR::ttypeType::UnsignedInteger:
16531663
case ASR::ttypeType::Real:
@@ -2279,6 +2289,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
22792289
case ASR::ttypeType::CPtr: {
22802290
return true;
22812291
}
2292+
case ASR::ttypeType::SymbolicExpression: {
2293+
return true;
2294+
}
22822295
case (ASR::ttypeType::Real) : {
22832296
ASR::Real_t *a2 = ASR::down_cast<ASR::Real_t>(a);
22842297
ASR::Real_t *b2 = ASR::down_cast<ASR::Real_t>(b);

src/libasr/codegen/asr_to_c.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,11 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
486486
dims = convert_dims_c(n_dims, m_dims, v_m_type, is_fixed_size);
487487
sub = format_type_c(dims, type_name, v_m_name, use_ref, dummy);
488488
}
489+
} else if (ASR::is_a<ASR::SymbolicExpression_t>(*v_m_type)) {
490+
headers.insert("symengine/cwrapper.h");
491+
std::string type_name = "basic";
492+
std::string v_m_name = v.m_name;
493+
sub = format_type_c("", type_name, v_m_name, use_ref, dummy);
489494
} else if (ASRUtils::is_logical(*v_m_type)) {
490495
bool is_fixed_size = true;
491496
dims = convert_dims_c(n_dims, m_dims, v_m_type, is_fixed_size);
@@ -1261,6 +1266,9 @@ R"( // Initialise Numpy
12611266
v.pop_back();
12621267
v.push_back("creal(" + src + ")");
12631268
v.push_back("cimag(" + src + ")");
1269+
} else if(value_type->type == ASR::ttypeType::SymbolicExpression){
1270+
v.pop_back();
1271+
v.push_back("basic_str(" + src + ")");
12641272
}
12651273
if (i+1!=x.n_values) {
12661274
tmp_gen += "\%s";

src/libasr/codegen/asr_to_c_cpp.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ R"(#include <stdio.h>
435435
sub = "double complex ";
436436
}
437437
}
438+
} else if (ASR::is_a<ASR::SymbolicExpression_t>(*return_var->m_type)) {
439+
sub = "basic ";
438440
} else if (ASR::is_a<ASR::CPtr_t>(*return_var->m_type)) {
439441
sub = "void* ";
440442
} else if (ASR::is_a<ASR::List_t>(*return_var->m_type)) {
@@ -676,6 +678,10 @@ R"(#include <stdio.h>
676678
v->m_intent == ASRUtils::intent_return_var ) {
677679
d += ";\n";
678680
}
681+
if (ASR::is_a<ASR::SymbolicExpression_t>(*v->m_type)) {
682+
std::string v_m_name = v->m_name;
683+
d += indent + "basic_new_stack(" + v_m_name + ");\n";
684+
}
679685
decl += check_tmp_buffer() + d;
680686
}
681687
if (ASR::is_a<ASR::TypeParameter_t>(*v->m_type)) {
@@ -1026,7 +1032,12 @@ R"(#include <stdio.h>
10261032
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
10271033
}
10281034
} else {
1029-
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
1035+
if (m_target_type->type == ASR::ttypeType::SymbolicExpression){
1036+
ASR::expr_t* m_value_expr = x.m_value;
1037+
src += alloc + indent + c_ds_api->get_deepcopy_symbolic(m_value_expr, value, target) + "\n";
1038+
} else {
1039+
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
1040+
}
10301041
}
10311042
} else {
10321043
src += indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
@@ -2367,7 +2378,6 @@ R"(#include <stdio.h>
23672378
}
23682379

23692380
void visit_IntrinsicFunction(const ASR::IntrinsicFunction_t &x) {
2370-
LCOMPILERS_ASSERT(x.n_args == 1)
23712381
std::string out;
23722382
switch (x.m_intrinsic_id) {
23732383
SET_INTRINSIC_NAME(Sin, "sin");
@@ -2383,16 +2393,34 @@ R"(#include <stdio.h>
23832393
SET_INTRINSIC_NAME(Exp, "exp");
23842394
SET_INTRINSIC_NAME(Exp2, "exp2");
23852395
SET_INTRINSIC_NAME(Expm1, "expm1");
2396+
SET_INTRINSIC_NAME(SymbolicSymbol, "Symbol");
2397+
SET_INTRINSIC_NAME(SymbolicPi, "pi");
2398+
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicAdd)): {
2399+
LCOMPILERS_ASSERT(x.n_args == 2);
2400+
this->visit_expr(*x.m_args[0]);
2401+
std::string arg1 = src;
2402+
this->visit_expr(*x.m_args[1]);
2403+
std::string arg2 = src;
2404+
out = arg1 + "," + arg2;
2405+
src = out;
2406+
break;
2407+
}
23862408
default : {
23872409
throw LCompilersException("IntrinsicFunction: `"
23882410
+ ASRUtils::get_intrinsic_name(x.m_intrinsic_id)
23892411
+ "` is not implemented");
23902412
}
23912413
}
23922414
headers.insert("math.h");
2393-
this->visit_expr(*x.m_args[0]);
2394-
out += "(" + src + ")";
2395-
src = out;
2415+
if (x.n_args == 0){
2416+
src = out;
2417+
} else if (x.n_args == 1) {
2418+
this->visit_expr(*x.m_args[0]);
2419+
if (x.m_intrinsic_id != static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicSymbol)) {
2420+
out += "(" + src + ")";
2421+
src = out;
2422+
}
2423+
}
23962424
}
23972425
};
23982426

src/libasr/codegen/c_utils.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <libasr/asr.h>
55
#include <libasr/asr_utils.h>
6+
#include <libasr/pass/intrinsic_function_registry.h>
67

78
namespace LCompilers {
89

@@ -631,6 +632,39 @@ class CCPPDSUtils {
631632
return result;
632633
}
633634

635+
std::string get_deepcopy_symbolic(ASR::expr_t *value_expr, std::string value, std::string target) {
636+
std::string result;
637+
if (ASR::is_a<ASR::Var_t>(*value_expr)) {
638+
result = "basic_assign(" + target + ", " + value + ");";
639+
} else if (ASR::is_a<ASR::IntrinsicFunction_t>(*value_expr)) {
640+
ASR::IntrinsicFunction_t* intrinsic_func = ASR::down_cast<ASR::IntrinsicFunction_t>(value_expr);
641+
int64_t intrinsic_id = intrinsic_func->m_intrinsic_id;
642+
switch (static_cast<LCompilers::ASRUtils::IntrinsicFunctions>(intrinsic_id)) {
643+
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicSymbol: {
644+
result = "symbol_set(" + target + ", " + value + ");";
645+
break;
646+
}
647+
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicAdd: {
648+
size_t delimiterPos = value.find(",");
649+
std::string leftPart = value.substr(0, delimiterPos);
650+
std::string rightPart = value.substr(delimiterPos + 1);
651+
result = "basic_add(" + target + ", " + leftPart + ", " + rightPart + ");";
652+
break;
653+
}
654+
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicPi: {
655+
result = "basic_const_pi(" + target + ");";
656+
break;
657+
}
658+
default: {
659+
throw LCompilersException("IntrinsicFunction: `"
660+
+ LCompilers::ASRUtils::get_intrinsic_name(intrinsic_id)
661+
+ "` is not implemented");
662+
}
663+
}
664+
}
665+
return result;
666+
}
667+
634668
std::string get_type(ASR::ttype_t *t) {
635669
LCOMPILERS_ASSERT(CUtils::is_non_primitive_DT(t));
636670
if (ASR::is_a<ASR::List_t>(*t)) {
@@ -698,6 +732,9 @@ class CCPPDSUtils {
698732
case ASR::ttypeType::Complex: {
699733
return "(%f, %f)";
700734
}
735+
case ASR::ttypeType::SymbolicExpression: {
736+
return "%s";
737+
}
701738
case ASR::ttypeType::Pointer: {
702739
if( !deref_ptr ) {
703740
return "%p";

0 commit comments

Comments
 (0)