Skip to content

Commit

Permalink
Merge branch 'main' into list_support
Browse files Browse the repository at this point in the history
  • Loading branch information
anutosh491 authored Oct 10, 2023
2 parents 5af8e0e + ac65227 commit 3e7830c
Show file tree
Hide file tree
Showing 89 changed files with 2,790 additions and 2,241 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython)

# Intrinsic Functions
RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any
RUN(NAME intrinsics_02 LABELS cpython llvm c) # floordiv

# lpython decorator
RUN(NAME lpython_decorator_01 LABELS cpython)
Expand Down
42 changes: 42 additions & 0 deletions integration_tests/intrinsics_02.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from lpython import Const, i32, f32, f64

foo: Const[i32] = 4
bar: Const[i32] = foo // 2

print(bar)
assert bar == 2

def floordiv1():
a: f64
b: f64
c: f64
a = 5.0
b = 2.0
c = a // b

print(c)
assert c == 2.0

def floordiv2():
a: Const[f32] = f32(5.0)
b: Const[f32] = f32(2.0)
c: f32
c = a // b

print(c)
assert c == f32(2.0)

def floordiv3():
a: f64
b: f64
c: f64
a = 5.0
b = -2.0
c = a // b

print(c)
assert c == -3.0

floordiv1()
floordiv2()
floordiv3()
3 changes: 3 additions & 0 deletions integration_tests/symbolics_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ def main0():
y: S = Symbol('y')
x = pi
z: S = x + y
x = z
print(x)
print(z)
assert(x == z)
assert(z == pi + y)
assert(z != S(2)*pi + y)

Expand Down
19 changes: 18 additions & 1 deletion integration_tests/symbolics_02.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from sympy import Symbol
from sympy import Symbol, pi
from lpython import S

def test_symbolic_operations():
x: S = Symbol('x')
y: S = Symbol('y')
p1: S = pi
p2: S = pi

# Addition
z: S = x + y
Expand Down Expand Up @@ -37,4 +39,19 @@ def test_symbolic_operations():
assert(c == S(0))
print(c)

# Comparison
b1: bool = p1 == p2
print(b1)
assert(b1 == True)
b2: bool = p1 != pi
print(b2)
assert(b2 == False)
b3: bool = p1 != x
print(b3)
assert(b3 == True)
b4: bool = pi == Symbol("x")
print(b4)
assert(b4 == False)


test_symbolic_operations()
49 changes: 49 additions & 0 deletions integration_tests/test_str_01.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,52 @@ def test_str_slice():
# TODO:
# assert a[0:5:-1] == ""

def test_str_isalpha():
a: str = "helloworld"
b: str = "hj kl"
c: str = "a12(){}A"
d: str = " "
res: bool = a.isalpha()
res2: bool = b.isalpha()
res3: bool = c.isalpha()
res4: bool = d.isalpha()
assert res == True
assert res2 == False
assert res3 == False
assert res4 == False


def test_str_title():
a: str = "hello world"
b: str = "hj'kl"
c: str = "hELlo wOrlD"
d: str = "{Hel1o}world"
res: str = a.title()
res2: str = b.title()
res3: str = c.title()
res4: str = d.title()
assert res == "Hello World"
assert res2 == "Hj'Kl"
assert res3 == "Hello World"
assert res4 == "{Hel1O}World"

def test_str_istitle():
a: str = "Hello World"
b: str = "Hj'kl"
c: str = "hELlo wOrlD"
d: str = " Hello"
e: str = " "
res: bool = a.istitle()
res2: bool = b.istitle()
res3: bool = c.istitle()
res4: bool = d.istitle()
res5: bool = e.istitle()
assert res == True
assert res2 == False
assert res3 == False
assert res4 == True
assert res5 == False

def test_str_repeat():
a: str
a = "Xyz"
Expand Down Expand Up @@ -88,5 +134,8 @@ def check():
test_str_join_empty_str()
test_str_join_empty_list()
test_constant_str_subscript()
test_str_title()
test_str_istitle()
test_str_isalpha()

check()
12 changes: 12 additions & 0 deletions integration_tests/test_str_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,17 @@ def is_ascii():
s = "123 45 6"
assert s.isascii() == True


def is_space():
assert "\n".isspace() == True
assert " ".isspace() == True
assert "\r".isspace() == True

s:str = " "
assert s.isspace() == True
s = "a"
assert s.isspace() == False

def check():
capitalize()
lower()
Expand All @@ -290,5 +301,6 @@ def check():
is_upper()
is_decimal()
is_ascii()
is_space()

check()
1 change: 1 addition & 0 deletions src/libasr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ set(SRC

asr_verify.cpp
asr_utils.cpp
casting_utils.cpp
diagnostics.cpp
stacktrace.cpp
string_utils.cpp
Expand Down
143 changes: 143 additions & 0 deletions src/libasr/casting_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include <libasr/casting_utils.h>
#include <libasr/asr_utils.h>

#include <map>


namespace LCompilers::CastingUtil {

// Data structure which contains priorities for
// intrinsic types defined in ASR
const std::map<ASR::ttypeType, int>& type2weight = {
{ASR::ttypeType::Complex, 4},
{ASR::ttypeType::Real, 3},
{ASR::ttypeType::Integer, 2},
{ASR::ttypeType::Logical, 1}
};

// Data structure which contains casting rules for non-equal
// intrinsic types defined in ASR
const std::map<std::pair<ASR::ttypeType, ASR::ttypeType>, ASR::cast_kindType>& type_rules = {
{std::make_pair(ASR::ttypeType::Complex, ASR::ttypeType::Real), ASR::cast_kindType::ComplexToReal},
{std::make_pair(ASR::ttypeType::Complex, ASR::ttypeType::Logical), ASR::cast_kindType::ComplexToLogical},
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Complex), ASR::cast_kindType::RealToComplex},
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Integer), ASR::cast_kindType::RealToInteger},
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::Logical), ASR::cast_kindType::RealToLogical},
{std::make_pair(ASR::ttypeType::Real, ASR::ttypeType::UnsignedInteger), ASR::cast_kindType::RealToUnsignedInteger},
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Complex), ASR::cast_kindType::IntegerToComplex},
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Real), ASR::cast_kindType::IntegerToReal},
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::Logical), ASR::cast_kindType::IntegerToLogical},
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::UnsignedInteger), ASR::cast_kindType::IntegerToUnsignedInteger},
{std::make_pair(ASR::ttypeType::Logical, ASR::ttypeType::Real), ASR::cast_kindType::LogicalToReal},
{std::make_pair(ASR::ttypeType::Logical, ASR::ttypeType::Integer), ASR::cast_kindType::LogicalToInteger},
{std::make_pair(ASR::ttypeType::UnsignedInteger, ASR::ttypeType::Integer), ASR::cast_kindType::UnsignedIntegerToInteger},
{std::make_pair(ASR::ttypeType::UnsignedInteger, ASR::ttypeType::Real), ASR::cast_kindType::UnsignedIntegerToReal},
{std::make_pair(ASR::ttypeType::Integer, ASR::ttypeType::SymbolicExpression), ASR::cast_kindType::IntegerToSymbolicExpression}
};

// Data structure which contains casting rules for equal intrinsic
// types but with different kinds.
const std::map<ASR::ttypeType, ASR::cast_kindType>& kind_rules = {
{ASR::ttypeType::Complex, ASR::cast_kindType::ComplexToComplex},
{ASR::ttypeType::Real, ASR::cast_kindType::RealToReal},
{ASR::ttypeType::Integer, ASR::cast_kindType::IntegerToInteger},
{ASR::ttypeType::UnsignedInteger, ASR::cast_kindType::UnsignedIntegerToUnsignedInteger}
};

int get_type_priority(ASR::ttypeType type) {
if( type2weight.find(type) == type2weight.end() ) {
return -1;
}

return type2weight.at(type);
}

int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr,
ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr,
ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type,
bool is_assign) {
ASR::ttype_t* left_type = ASRUtils::expr_type(left_expr);
ASR::ttype_t* right_type = ASRUtils::expr_type(right_expr);
if( ASR::is_a<ASR::Const_t>(*left_type) ) {
left_type = ASRUtils::get_contained_type(left_type);
}
if( ASR::is_a<ASR::Const_t>(*right_type) ) {
right_type = ASRUtils::get_contained_type(right_type);
}
left_type = ASRUtils::type_get_past_pointer(left_type);
right_type = ASRUtils::type_get_past_pointer(right_type);
if( ASRUtils::check_equal_type(left_type, right_type) ||
ASRUtils::is_character(*left_type) || ASRUtils::is_character(*right_type) ) {
return 2;
}
if( is_assign ) {
if( ASRUtils::is_real(*left_type) && ASRUtils::is_integer(*right_type)) {
throw SemanticError("Assigning integer to float is not supported",
right_expr->base.loc);
}
if ( ASRUtils::is_complex(*left_type) && !ASRUtils::is_complex(*right_type)) {
throw SemanticError("Assigning non-complex to complex is not supported",
right_expr->base.loc);
}
dest_expr = left_expr, dest_type = left_type;
src_expr = right_expr, src_type = right_type;
return 1;
}

int casted_expr_signal = 2;
ASR::ttypeType left_Type = left_type->type, right_Type = right_type->type;
int left_kind = ASRUtils::extract_kind_from_ttype_t(left_type);
int right_kind = ASRUtils::extract_kind_from_ttype_t(right_type);
int left_priority = get_type_priority(left_Type);
int right_priority = get_type_priority(right_Type);
if( left_priority > right_priority ) {
src_expr = right_expr, src_type = right_type;
dest_expr = left_expr, dest_type = left_type;
casted_expr_signal = 1;
} else if( left_priority < right_priority ) {
src_expr = left_expr, src_type = left_type;
dest_expr = right_expr, dest_type = right_type;
casted_expr_signal = 0;
} else {
if( left_kind > right_kind ) {
src_expr = right_expr, src_type = right_type;
dest_expr = left_expr, dest_type = left_type;
casted_expr_signal = 1;
} else if( left_kind < right_kind ) {
src_expr = left_expr, src_type = left_type;
dest_expr = right_expr, dest_type = right_type;
casted_expr_signal = 0;
} else {
return 2;
}
}

return casted_expr_signal;
}

ASR::expr_t* perform_casting(ASR::expr_t* expr, ASR::ttype_t* src,
ASR::ttype_t* dest, Allocator& al,
const Location& loc) {
ASR::ttypeType src_type = src->type;
ASR::ttypeType dest_type = dest->type;
ASR::cast_kindType cast_kind;
if( src_type == dest_type ) {
if( kind_rules.find(src_type) == kind_rules.end() ) {
return expr;
}
cast_kind = kind_rules.at(src_type);
} else {
std::pair<ASR::ttypeType, ASR::ttypeType> cast_key = std::make_pair(src_type, dest_type);
if( type_rules.find(cast_key) == type_rules.end() ) {
return expr;
}
cast_kind = type_rules.at(cast_key);
}
if( ASRUtils::check_equal_type(src, dest, true) ) {
return expr;
}
// TODO: Fix loc
return ASRUtils::EXPR(ASRUtils::make_Cast_t_value(al, loc, expr,
cast_kind, dest));
}
}
21 changes: 21 additions & 0 deletions src/libasr/casting_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef LFORTRAN_CASTING_UTILS_H
#define LFORTRAN_CASTING_UTILS_H


#include <libasr/asr.h>

namespace LCompilers::CastingUtil {

int get_type_priority(ASR::ttypeType type);

int get_src_dest(ASR::expr_t* left_expr, ASR::expr_t* right_expr,
ASR::expr_t*& src_expr, ASR::expr_t*& dest_expr,
ASR::ttype_t*& src_type, ASR::ttype_t*& dest_type,
bool is_assign);

ASR::expr_t* perform_casting(ASR::expr_t* expr, ASR::ttype_t* src,
ASR::ttype_t* dest, Allocator& al,
const Location& loc);
}

#endif // LFORTRAN_CASTING_UTILS_H
1 change: 1 addition & 0 deletions src/libasr/codegen/asr_to_c_cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2800,6 +2800,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) {
SET_INTRINSIC_NAME(Expm1, "expm1");
SET_INTRINSIC_NAME(Trunc, "trunc");
SET_INTRINSIC_NAME(Fix, "fix");
SET_INTRINSIC_NAME(FloorDiv, "floordiv");
default : {
throw LCompilersException("IntrinsicScalarFunction: `"
+ ASRUtils::get_intrinsic_name(x.m_intrinsic_id)
Expand Down
6 changes: 3 additions & 3 deletions src/libasr/codegen/asr_to_wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2299,7 +2299,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {

void visit_RealConstant(const ASR::RealConstant_t &x) {
double val = x.m_r;
int a_kind = ((ASR::Real_t *)(&(x.m_type->base)))->m_kind;
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
switch (a_kind) {
case 4: {
m_wa.emit_f32_const(val);
Expand All @@ -2318,7 +2318,7 @@ class ASRToWASMVisitor : public ASR::BaseVisitor<ASRToWASMVisitor> {

void visit_LogicalConstant(const ASR::LogicalConstant_t &x) {
bool val = x.m_value;
int a_kind = ((ASR::Logical_t *)(&(x.m_type->base)))->m_kind;
int a_kind = ASRUtils::extract_kind_from_ttype_t(x.m_type);
switch (a_kind) {
case 4: {
m_wa.emit_i32_const(val);
Expand Down Expand Up @@ -3222,7 +3222,7 @@ Result<Vec<uint8_t>> asr_to_wasm_bytes_stream(ASR::TranslationUnit_t &asr,
pass_options.dump_all_passes = co.dump_all_passes;
std::vector<std::string> passes = {"pass_array_by_data", "array_op",
"implied_do_loops", "print_arr", "do_loops", "select_case",
"intrinsic_function", "nested_vars", "unused_functions"};
"nested_vars", "unused_functions", "intrinsic_function"};
LCompilers::PassManager pass_manager;
pass_manager.apply_passes(al, &asr, passes, pass_options, diagnostics);

Expand Down
Loading

0 comments on commit 3e7830c

Please sign in to comment.