Skip to content

Commit

Permalink
Intial Implementation for SymbolicExpression ttype (lcompilers#1846)
Browse files Browse the repository at this point in the history
Co-authored-by: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com>
Co-authored-by: Shaikh Ubaid <shaikhubaid769@gmail.com>
Co-authored-by: Ondřej Čertík <ondrej@certik.us>
  • Loading branch information
4 people committed Jun 19, 2023
1 parent d0b957d commit d6a6d8b
Show file tree
Hide file tree
Showing 14 changed files with 370 additions and 25 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,47 @@ jobs:
run: |
cd integration_tests
./run_tests.py -b cpython_py c_py
sympy:
name: Run SymPy tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- uses: mamba-org/setup-micromamba@v1
with:
environment-file: ci/environment.yml
create-args: >-
python=3.10
bison=3.4
symengine=0.9.0
sympy=1.11.1
- uses: hendrikmuhs/ccache-action@main
with:
key: ${{ github.job }}-${{ matrix.os }}

- name: Build
shell: bash -l {0}
run: |
./build0.sh
cmake . -G"Unix Makefiles" \
-DCMAKE_BUILD_TYPE=Debug \
-DWITH_LLVM=yes \
-DLPYTHON_BUILD_ALL=yes \
-DWITH_STACKTRACE=no \
-DWITH_RUNTIME_STACKTRACE=no \
-DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
-DCMAKE_INSTALL_PREFIX=`pwd`/inst \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build . -j16 --target install
- name: Test
shell: bash -l {0}
run: |
cd integration_tests
./run_tests.py -b c_sym cpython_sym
31 changes: 29 additions & 2 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,31 @@ macro(RUN_UTIL RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_ENABLE_CPYTHON RUN
if (${fail})
set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
endif()
elseif((KIND STREQUAL "cpython") OR (KIND STREQUAL "cpython_py"))
elseif(KIND STREQUAL "c_sym")
add_custom_command(
OUTPUT ${name}.c
COMMAND ${LPYTHON} ${extra_args} --show-c
${CMAKE_CURRENT_SOURCE_DIR}/${file_name}.py > ${name}.c
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${file_name}.py
VERBATIM)
add_executable(${name} ${name}.c ${extra_files})
target_include_directories(${name} PRIVATE ${CMAKE_SOURCE_DIR}
"${Python_INCLUDE_DIRS}/..")
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE C)
if (APPLE)
set(SYMENGINE_LIB "${Python_LIBRARY_DIRS}/libsymengine.dylib")
else()
set(SYMENGINE_LIB "${Python_LIBRARY_DIRS}/libsymengine.so")
endif()
target_link_libraries(${name} lpython_rtlib ${SYMENGINE_LIB})
add_test(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name})
if (labels)
set_tests_properties(${name} PROPERTIES LABELS "${labels}")
endif()
if (${fail})
set_tests_properties(${name} PROPERTIES WILL_FAIL TRUE)
endif()
elseif((KIND STREQUAL "cpython") OR (KIND STREQUAL "cpython_py") OR (KIND STREQUAL "cpython_sym"))
# CPython test
if (extra_files)
set(PY_MOD "${name}_mod")
Expand Down Expand Up @@ -267,7 +291,7 @@ macro(RUN)
if ((NOT DISABLE_FAST) AND (NOT RUN_NOFAST))
set(RUN_EXTRA_ARGS ${RUN_EXTRA_ARGS} --fast)
set(RUN_NAME "${RUN_NAME}_FAST")
list(REMOVE_ITEM RUN_LABELS cpython cpython_py) # remove cpython, cpython_py from --fast test
list(REMOVE_ITEM RUN_LABELS cpython cpython_sym cpython_py) # remove cpython, cpython_sym, cpython_py from --fast test
RUN_UTIL(RUN_FAIL RUN_NAME RUN_FILE_NAME RUN_LABELS RUN_ENABLE_CPYTHON RUN_EXTRAFILES RUN_EXTRA_ARGS)
endif()
endmacro(RUN)
Expand Down Expand Up @@ -552,6 +576,9 @@ RUN(NAME structs_24 LABELS cpython llvm c)
RUN(NAME structs_25 LABELS cpython llvm c)
RUN(NAME structs_26 LABELS cpython llvm c)
RUN(NAME structs_27 LABELS cpython llvm c)

RUN(NAME symbolics_01 LABELS cpython_sym c_sym)

RUN(NAME sizeof_01 LABELS llvm c
EXTRAFILES sizeof_01b.c)
RUN(NAME sizeof_02 LABELS cpython llvm c)
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

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

Expand Down
11 changes: 11 additions & 0 deletions integration_tests/symbolics_01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from sympy import Symbol, pi
from lpython import S

def main0():
x: S = Symbol('x')
y: S = Symbol('y')
x = pi
z: S = x + y
print(z)

main0()
7 changes: 7 additions & 0 deletions src/bin/lpython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1244,8 +1244,14 @@ int link_executable(const std::vector<std::string> &infiles,
cmd += s + " ";
}
cmd += " -I " + rtlib_header_dir;
if (compiler_options.enable_symengine) {
cmd += " -I${CONDA_PREFIX}/include";
}
cmd += " -L" + base_path
+ " -Wl,-rpath," + base_path + " -l" + runtime_lib + " -lm";
if (compiler_options.enable_symengine) {
cmd += " -L$CONDA_PREFIX/lib -Wl,-rpath -Wl,$CONDA_PREFIX/lib -lsymengine";
}
if (compiler_options.enable_cpython) {
std::string py_version = "3.10";
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"()";
Expand Down Expand Up @@ -1565,6 +1571,7 @@ int main(int argc, char *argv[])
app.add_flag("--get-rtl-dir", print_rtl_dir, "Print the path to the runtime library file");
app.add_flag("--verbose", compiler_options.verbose, "Print debugging statements");
app.add_flag("--enable-cpython", compiler_options.enable_cpython, "Enable CPython runtime");
app.add_flag("--enable-symengine", compiler_options.enable_symengine, "Enable Symengine runtime");
app.add_flag("--link-numpy", compiler_options.link_numpy, "Enable NumPy runtime (implies --enable-cpython)");

// LSP specific options
Expand Down
1 change: 1 addition & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ ttype
| Allocatable(ttype type)
| Const(ttype type)
| CPtr()
| SymbolicExpression()
| TypeParameter(identifier param)
| Array(ttype type, dimension* dims)
| FunctionType(ttype* arg_types, ttype? return_var_type,
Expand Down
13 changes: 13 additions & 0 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ static inline std::string type_to_str(const ASR::ttype_t *t)
ASR::TypeParameter_t* tp = ASR::down_cast<ASR::TypeParameter_t>(t);
return tp->m_param;
}
case ASR::ttypeType::SymbolicExpression: {
return "symbolic expression";
}
default : throw LCompilersException("Not implemented " + std::to_string(t->type) + ".");
}
}
Expand Down Expand Up @@ -1151,6 +1154,9 @@ static inline std::string get_type_code(const ASR::ttype_t *t, bool use_undersco
return "Const[" + get_type_code(p->m_type, use_underscore_sep,
encode_dimensions_, set_dimensional_hint) + "]";
}
case ASR::ttypeType::SymbolicExpression: {
return "S";
}
default: {
throw LCompilersException("Type encoding not implemented for "
+ std::to_string(t->type));
Expand Down Expand Up @@ -1286,6 +1292,9 @@ static inline std::string type_to_str_python(const ASR::ttype_t *t,
ASR::TypeParameter_t *p = ASR::down_cast<ASR::TypeParameter_t>(t);
return p->m_param;
}
case ASR::ttypeType::SymbolicExpression: {
return "S";
}
default : throw LCompilersException("Not implemented " + std::to_string(t->type));
}
}
Expand Down Expand Up @@ -1648,6 +1657,7 @@ inline int extract_dimensions_from_ttype(ASR::ttype_t *x,
n_dims = extract_dimensions_from_ttype(ASR::down_cast<ASR::Const_t>(x)->m_type, m_dims);
break;
}
case ASR::ttypeType::SymbolicExpression:
case ASR::ttypeType::Integer:
case ASR::ttypeType::UnsignedInteger:
case ASR::ttypeType::Real:
Expand Down Expand Up @@ -2279,6 +2289,9 @@ inline bool types_equal(ASR::ttype_t *a, ASR::ttype_t *b,
case ASR::ttypeType::CPtr: {
return true;
}
case ASR::ttypeType::SymbolicExpression: {
return true;
}
case (ASR::ttypeType::Real) : {
ASR::Real_t *a2 = ASR::down_cast<ASR::Real_t>(a);
ASR::Real_t *b2 = ASR::down_cast<ASR::Real_t>(b);
Expand Down
8 changes: 8 additions & 0 deletions src/libasr/codegen/asr_to_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,11 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
dims = convert_dims_c(n_dims, m_dims, v_m_type, is_fixed_size);
sub = format_type_c(dims, type_name, v_m_name, use_ref, dummy);
}
} else if (ASR::is_a<ASR::SymbolicExpression_t>(*v_m_type)) {
headers.insert("symengine/cwrapper.h");
std::string type_name = "basic";
std::string v_m_name = v.m_name;
sub = format_type_c("", type_name, v_m_name, use_ref, dummy);
} else if (ASRUtils::is_logical(*v_m_type)) {
bool is_fixed_size = true;
dims = convert_dims_c(n_dims, m_dims, v_m_type, is_fixed_size);
Expand Down Expand Up @@ -1261,6 +1266,9 @@ R"( // Initialise Numpy
v.pop_back();
v.push_back("creal(" + src + ")");
v.push_back("cimag(" + src + ")");
} else if(value_type->type == ASR::ttypeType::SymbolicExpression){
v.pop_back();
v.push_back("basic_str(" + src + ")");
}
if (i+1!=x.n_values) {
tmp_gen += "\%s";
Expand Down
38 changes: 33 additions & 5 deletions src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ R"(#include <stdio.h>
sub = "double complex ";
}
}
} else if (ASR::is_a<ASR::SymbolicExpression_t>(*return_var->m_type)) {
sub = "basic ";
} else if (ASR::is_a<ASR::CPtr_t>(*return_var->m_type)) {
sub = "void* ";
} else if (ASR::is_a<ASR::List_t>(*return_var->m_type)) {
Expand Down Expand Up @@ -676,6 +678,10 @@ R"(#include <stdio.h>
v->m_intent == ASRUtils::intent_return_var ) {
d += ";\n";
}
if (ASR::is_a<ASR::SymbolicExpression_t>(*v->m_type)) {
std::string v_m_name = v->m_name;
d += indent + "basic_new_stack(" + v_m_name + ");\n";
}
decl += check_tmp_buffer() + d;
}
if (ASR::is_a<ASR::TypeParameter_t>(*v->m_type)) {
Expand Down Expand Up @@ -1026,7 +1032,12 @@ R"(#include <stdio.h>
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
}
} else {
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
if (m_target_type->type == ASR::ttypeType::SymbolicExpression){
ASR::expr_t* m_value_expr = x.m_value;
src += alloc + indent + c_ds_api->get_deepcopy_symbolic(m_value_expr, value, target) + "\n";
} else {
src += alloc + indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
}
}
} else {
src += indent + c_ds_api->get_deepcopy(m_target_type, value, target) + "\n";
Expand Down Expand Up @@ -2367,7 +2378,6 @@ R"(#include <stdio.h>
}

void visit_IntrinsicFunction(const ASR::IntrinsicFunction_t &x) {
LCOMPILERS_ASSERT(x.n_args == 1)
std::string out;
switch (x.m_intrinsic_id) {
SET_INTRINSIC_NAME(Sin, "sin");
Expand All @@ -2383,16 +2393,34 @@ R"(#include <stdio.h>
SET_INTRINSIC_NAME(Exp, "exp");
SET_INTRINSIC_NAME(Exp2, "exp2");
SET_INTRINSIC_NAME(Expm1, "expm1");
SET_INTRINSIC_NAME(SymbolicSymbol, "Symbol");
SET_INTRINSIC_NAME(SymbolicPi, "pi");
case (static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicAdd)): {
LCOMPILERS_ASSERT(x.n_args == 2);
this->visit_expr(*x.m_args[0]);
std::string arg1 = src;
this->visit_expr(*x.m_args[1]);
std::string arg2 = src;
out = arg1 + "," + arg2;
src = out;
break;
}
default : {
throw LCompilersException("IntrinsicFunction: `"
+ ASRUtils::get_intrinsic_name(x.m_intrinsic_id)
+ "` is not implemented");
}
}
headers.insert("math.h");
this->visit_expr(*x.m_args[0]);
out += "(" + src + ")";
src = out;
if (x.n_args == 0){
src = out;
} else if (x.n_args == 1) {
this->visit_expr(*x.m_args[0]);
if (x.m_intrinsic_id != static_cast<int64_t>(ASRUtils::IntrinsicFunctions::SymbolicSymbol)) {
out += "(" + src + ")";
src = out;
}
}
}
};

Expand Down
37 changes: 37 additions & 0 deletions src/libasr/codegen/c_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <libasr/asr.h>
#include <libasr/asr_utils.h>
#include <libasr/pass/intrinsic_function_registry.h>

namespace LCompilers {

Expand Down Expand Up @@ -631,6 +632,39 @@ class CCPPDSUtils {
return result;
}

std::string get_deepcopy_symbolic(ASR::expr_t *value_expr, std::string value, std::string target) {
std::string result;
if (ASR::is_a<ASR::Var_t>(*value_expr)) {
result = "basic_assign(" + target + ", " + value + ");";
} else if (ASR::is_a<ASR::IntrinsicFunction_t>(*value_expr)) {
ASR::IntrinsicFunction_t* intrinsic_func = ASR::down_cast<ASR::IntrinsicFunction_t>(value_expr);
int64_t intrinsic_id = intrinsic_func->m_intrinsic_id;
switch (static_cast<LCompilers::ASRUtils::IntrinsicFunctions>(intrinsic_id)) {
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicSymbol: {
result = "symbol_set(" + target + ", " + value + ");";
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicAdd: {
size_t delimiterPos = value.find(",");
std::string leftPart = value.substr(0, delimiterPos);
std::string rightPart = value.substr(delimiterPos + 1);
result = "basic_add(" + target + ", " + leftPart + ", " + rightPart + ");";
break;
}
case LCompilers::ASRUtils::IntrinsicFunctions::SymbolicPi: {
result = "basic_const_pi(" + target + ");";
break;
}
default: {
throw LCompilersException("IntrinsicFunction: `"
+ LCompilers::ASRUtils::get_intrinsic_name(intrinsic_id)
+ "` is not implemented");
}
}
}
return result;
}

std::string get_type(ASR::ttype_t *t) {
LCOMPILERS_ASSERT(CUtils::is_non_primitive_DT(t));
if (ASR::is_a<ASR::List_t>(*t)) {
Expand Down Expand Up @@ -698,6 +732,9 @@ class CCPPDSUtils {
case ASR::ttypeType::Complex: {
return "(%f, %f)";
}
case ASR::ttypeType::SymbolicExpression: {
return "%s";
}
case ASR::ttypeType::Pointer: {
if( !deref_ptr ) {
return "%p";
Expand Down
Loading

0 comments on commit d6a6d8b

Please sign in to comment.