Skip to content

Commit acb5499

Browse files
authored
Merge branch 'main' into enum_struct
2 parents db132ed + 1aad65e commit acb5499

19 files changed

+375
-59
lines changed

integration_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ RUN(NAME bindc_01 LABELS cpython llvm c)
288288
RUN(NAME bindc_02 LABELS cpython llvm c)
289289
RUN(NAME bindc_04 LABELS llvm c)
290290
RUN(NAME bindc_07 LABELS cpython llvm c)
291+
RUN(NAME bindc_08 LABELS cpython llvm c)
291292
RUN(NAME bindc_09 LABELS cpython llvm c)
292293
RUN(NAME exit_01 LABELS cpython llvm c)
293294
RUN(NAME exit_02 FAIL LABELS cpython llvm c)
@@ -507,6 +508,7 @@ RUN(NAME test_str_comparison LABELS cpython llvm c)
507508
RUN(NAME test_bit_length LABELS cpython llvm c)
508509
RUN(NAME str_to_list_cast LABELS cpython llvm c)
509510
RUN(NAME test_sys_01 LABELS cpython llvm c)
511+
RUN(NAME intent_01 LABELS cpython llvm)
510512

511513

512514
RUN(NAME test_package_01 LABELS cpython llvm)

integration_tests/bindc_08.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# file: main.py
2+
from lpython import CPtr, i32, dataclass, c_p_pointer, Pointer, empty_c_void_p, p_c_pointer
3+
4+
from numpy import empty
5+
6+
@dataclass
7+
class Foo:
8+
x: i32
9+
y: i32
10+
11+
def init(foos_ptr: CPtr) -> None:
12+
foos: Pointer[Foo[1]] = c_p_pointer(foos_ptr, Foo[1])
13+
foos[0] = Foo(3, 2)
14+
15+
def main() -> None:
16+
foos: Foo[1] = empty(1, dtype=Foo)
17+
foos_ptr: CPtr = empty_c_void_p()
18+
foos[0] = Foo(0, 1)
19+
p_c_pointer(foos, foos_ptr)
20+
init(foos_ptr)
21+
print("foos[0].x = ", foos[0].x)
22+
print("foos[0].y = ", foos[0].y)
23+
assert foos[0].x == 3
24+
assert foos[0].y == 2
25+
26+
main()

integration_tests/intent_01.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from lpython import i32, u32, f64, dataclass, In, Out, InOut
2+
3+
@dataclass
4+
class Foo:
5+
p: i32
6+
7+
def f(x: i32, y: In[f64], z: InOut[list[u32]], w: Out[Foo]):
8+
assert (x == -12)
9+
assert abs(y - (4.44)) <= 1e-12
10+
z.append(u32(5))
11+
w.p = 24
12+
13+
14+
def main0():
15+
a: i32 = (-12)
16+
b: f64 = 4.44
17+
c: list[u32] = [u32(1), u32(2), u32(3), u32(4)]
18+
d: Foo = Foo(25)
19+
20+
print(a, b, c, d.p)
21+
22+
f(a, b, c, d)
23+
assert c[-1] == u32(5)
24+
assert d.p == 24
25+
26+
main0()

src/libasr/ASR.asdl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ stmt
207207
| ListAppend(expr a, expr ele)
208208
| AssociateBlockCall(symbol m)
209209
| SelectType(expr selector, type_stmt* body, stmt* default)
210-
| CPtrToPointer(expr cptr, expr ptr, expr? shape)
210+
| CPtrToPointer(expr cptr, expr ptr, expr? shape, expr? lower_bounds)
211211
| BlockCall(int label, symbol m)
212212
| SetInsert(expr a, expr ele)
213213
| SetRemove(expr a, expr ele)

src/libasr/codegen/asr_to_c.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,14 +1090,19 @@ R"(
10901090
std::string dest_src = std::move(src);
10911091
src = "";
10921092
std::string indent(indentation_level*indentation_spaces, ' ');
1093+
ASR::ArrayConstant_t* lower_bounds = nullptr;
1094+
if( x.m_lower_bounds ) {
1095+
LCOMPILERS_ASSERT(ASR::is_a<ASR::ArrayConstant_t>(*x.m_lower_bounds));
1096+
lower_bounds = ASR::down_cast<ASR::ArrayConstant_t>(x.m_lower_bounds);
1097+
}
10931098
if( ASRUtils::is_array(ASRUtils::expr_type(x.m_ptr)) ) {
10941099
std::string dim_set_code = "";
10951100
ASR::dimension_t* m_dims = nullptr;
10961101
int n_dims = ASRUtils::extract_dimensions_from_ttype(ASRUtils::expr_type(x.m_ptr), m_dims);
10971102
dim_set_code = indent + dest_src + "->n_dims = " + std::to_string(n_dims) + ";\n";
10981103
for( int i = 0; i < n_dims; i++ ) {
1099-
if( m_dims[i].m_start ) {
1100-
visit_expr(*m_dims[i].m_start);
1104+
if( lower_bounds ) {
1105+
visit_expr(*lower_bounds->m_args[i]);
11011106
} else {
11021107
src = "0";
11031108
}

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,6 +4400,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
44004400
llvm_cptr = builder->CreateBitCast(llvm_cptr, llvm_fptr_data_type->getPointerTo());
44014401
builder->CreateStore(llvm_cptr, fptr_data);
44024402
llvm::Value* prod = llvm::ConstantInt::get(context, llvm::APInt(32, 1));
4403+
ASR::ArrayConstant_t* lower_bounds = nullptr;
4404+
if( x.m_lower_bounds ) {
4405+
LCOMPILERS_ASSERT(ASR::is_a<ASR::ArrayConstant_t>(*x.m_lower_bounds));
4406+
lower_bounds = ASR::down_cast<ASR::ArrayConstant_t>(x.m_lower_bounds);
4407+
LCOMPILERS_ASSERT(fptr_rank == (int) lower_bounds->n_args);
4408+
}
44034409
for( int i = 0; i < fptr_rank; i++ ) {
44044410
llvm::Value* curr_dim = llvm::ConstantInt::get(context, llvm::APInt(32, i));
44054411
llvm::Value* desi = arr_descr->get_pointer_to_dimension_descriptor(fptr_des, curr_dim);
@@ -4409,6 +4415,13 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
44094415
builder->CreateStore(prod, desi_stride);
44104416
llvm::Value* i32_one = llvm::ConstantInt::get(context, llvm::APInt(32, 1));
44114417
llvm::Value* new_lb = i32_one;
4418+
if( lower_bounds ) {
4419+
int ptr_loads_copy = ptr_loads;
4420+
ptr_loads = 2;
4421+
this->visit_expr_wrapper(lower_bounds->m_args[i], true);
4422+
ptr_loads = ptr_loads_copy;
4423+
new_lb = tmp;
4424+
}
44124425
llvm::Value* new_ub = shape_data ? CreateLoad(llvm_utils->create_ptr_gep(shape_data, i)) : i32_one;
44134426
builder->CreateStore(new_lb, desi_lb);
44144427
llvm::Value* new_size = builder->CreateAdd(builder->CreateSub(new_ub, new_lb), i32_one);
@@ -6048,46 +6061,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
60486061
for (size_t i=0; i < x.n_args; i++) {
60496062
llvm::Value *llvm_el = llvm_utils->create_gep(p_fxn, i);
60506063
ASR::expr_t *el = x.m_args[i];
6051-
llvm::Value *llvm_val;
6052-
if (ASR::is_a<ASR::Integer_t>(*x.m_type)) {
6053-
ASR::IntegerConstant_t *ci = ASR::down_cast<ASR::IntegerConstant_t>(el);
6054-
switch (ASR::down_cast<ASR::Integer_t>(x.m_type)->m_kind) {
6055-
case (4) : {
6056-
int32_t el_value = ci->m_n;
6057-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(32, static_cast<int32_t>(el_value), true));
6058-
break;
6059-
}
6060-
case (8) : {
6061-
int64_t el_value = ci->m_n;
6062-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(32, el_value, true));
6063-
break;
6064-
}
6065-
default :
6066-
throw CodeGenError("ConstArray integer kind not supported yet");
6067-
}
6068-
} else if (ASR::is_a<ASR::Real_t>(*x.m_type)) {
6069-
ASR::RealConstant_t *cr = ASR::down_cast<ASR::RealConstant_t>(el);
6070-
switch (ASR::down_cast<ASR::Real_t>(x.m_type)->m_kind) {
6071-
case (4) : {
6072-
float el_value = cr->m_r;
6073-
llvm_val = llvm::ConstantFP::get(context, llvm::APFloat(el_value));
6074-
break;
6075-
}
6076-
case (8) : {
6077-
double el_value = cr->m_r;
6078-
llvm_val = llvm::ConstantFP::get(context, llvm::APFloat(el_value));
6079-
break;
6080-
}
6081-
default :
6082-
throw CodeGenError("ConstArray real kind not supported yet");
6083-
}
6084-
} else if (ASR::is_a<ASR::Logical_t>(*x.m_type)) {
6085-
ASR::LogicalConstant_t *cr = ASR::down_cast<ASR::LogicalConstant_t>(el);
6086-
llvm_val = llvm::ConstantInt::get(context, llvm::APInt(1, cr->m_value));
6087-
} else {
6088-
throw CodeGenError("ConstArray type not supported yet");
6089-
}
6090-
builder->CreateStore(llvm_val, llvm_el);
6064+
int64_t ptr_loads_copy = ptr_loads;
6065+
ptr_loads = 2;
6066+
this->visit_expr_wrapper(el, true);
6067+
ptr_loads = ptr_loads_copy;
6068+
builder->CreateStore(tmp, llvm_el);
60916069
}
60926070
// Return the vector as float* type:
60936071
tmp = llvm_utils->create_gep(p_fxn, 0);

src/libasr/codegen/llvm_utils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ namespace LCompilers {
311311
std::map<std::string, std::map<std::string, int>>& name2memidx) {
312312
switch( asr_type->type ) {
313313
case ASR::ttypeType::Integer:
314+
case ASR::ttypeType::UnsignedInteger:
314315
case ASR::ttypeType::Real:
315316
case ASR::ttypeType::Logical:
316317
case ASR::ttypeType::Complex: {
@@ -2635,7 +2636,7 @@ namespace LCompilers {
26352636
*
26362637
* int i = 0;
26372638
* int j = end_point - 1;
2638-
*
2639+
*
26392640
* tmp;
26402641
*
26412642
* while(j > i) {

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,29 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
15811581
}
15821582
}
15831583

1584+
AST::expr_t* get_var_intent_and_annotation(AST::expr_t *annotation, ASR::intentType &intent) {
1585+
if (AST::is_a<AST::Subscript_t>(*annotation)) {
1586+
AST::Subscript_t *s = AST::down_cast<AST::Subscript_t>(annotation);
1587+
if (AST::is_a<AST::Name_t>(*s->m_value)) {
1588+
std::string ann_name = AST::down_cast<AST::Name_t>(s->m_value)->m_id;
1589+
if (ann_name == "In") {
1590+
intent = ASRUtils::intent_in;
1591+
return s->m_slice;
1592+
} else if (ann_name == "InOut") {
1593+
intent = ASRUtils::intent_inout;
1594+
return s->m_slice;
1595+
} else if (ann_name == "Out") {
1596+
intent = ASRUtils::intent_out;
1597+
return s->m_slice;
1598+
}
1599+
return annotation;
1600+
} else {
1601+
throw SemanticError("Only Name in Subscript supported for now in annotation", annotation->base.loc);
1602+
}
1603+
}
1604+
return annotation;
1605+
}
1606+
15841607
// Convert Python AST type annotation to an ASR type
15851608
// Examples:
15861609
// i32, i64, f32, f64
@@ -2490,6 +2513,35 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
24902513
current_scope->add_or_overwrite_symbol(var_name, v_sym);
24912514
}
24922515

2516+
#define fill_shape_and_lower_bound_for_CPtrToPointer() ASR::dimension_t* target_dims = nullptr; \
2517+
int target_n_dims = ASRUtils::extract_dimensions_from_ttype(target_type, target_dims); \
2518+
ASR::expr_t* target_shape = nullptr; \
2519+
ASR::expr_t* lower_bounds = nullptr; \
2520+
if( target_n_dims > 0 ) { \
2521+
Vec<ASR::expr_t*> sizes, lbs; \
2522+
sizes.reserve(al, target_n_dims); \
2523+
lbs.reserve(al, target_n_dims); \
2524+
bool success = true; \
2525+
for( int i = 0; i < target_n_dims; i++ ) { \
2526+
if( target_dims->m_length == nullptr ) { \
2527+
success = false; \
2528+
break; \
2529+
} \
2530+
sizes.push_back(al, target_dims->m_length); \
2531+
lbs.push_back(al, ASRUtils::EXPR(ASR::make_IntegerConstant_t( \
2532+
al, loc, 0, ASRUtils::TYPE( \
2533+
ASR::make_Integer_t(al, loc, 4, nullptr, 0))))); \
2534+
} \
2535+
if( success ) { \
2536+
target_shape = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, \
2537+
loc, sizes.p, sizes.size(), ASRUtils::expr_type(target_dims[0].m_length), \
2538+
ASR::arraystorageType::RowMajor)); \
2539+
lower_bounds = ASRUtils::EXPR(ASR::make_ArrayConstant_t(al, \
2540+
loc, lbs.p, lbs.size(), ASRUtils::expr_type(lbs[0]), \
2541+
ASR::arraystorageType::RowMajor)); \
2542+
} \
2543+
} \
2544+
24932545
ASR::asr_t* create_CPtrToPointerFromArgs(AST::expr_t* ast_cptr, AST::expr_t* ast_pptr,
24942546
AST::expr_t* ast_type_expr, const Location& loc) {
24952547
this->visit_expr(*ast_cptr);
@@ -2509,8 +2561,8 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
25092561
);
25102562
throw SemanticAbort();
25112563
}
2512-
return ASR::make_CPtrToPointer_t(al, loc, cptr,
2513-
pptr, nullptr);
2564+
fill_shape_and_lower_bound_for_CPtrToPointer();
2565+
return ASR::make_CPtrToPointer_t(al, loc, cptr, pptr, target_shape, lower_bounds);
25142566
}
25152567

25162568
void visit_AnnAssignUtil(const AST::AnnAssign_t& x, std::string& var_name,
@@ -3741,7 +3793,9 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
37413793
if (x.m_args.m_args[i].m_annotation == nullptr) {
37423794
throw SemanticError("Argument does not have a type", loc);
37433795
}
3744-
ASR::ttype_t *arg_type = ast_expr_to_asr_type(x.base.base.loc, *x.m_args.m_args[i].m_annotation);
3796+
ASR::intentType s_intent = ASRUtils::intent_unspecified;
3797+
AST::expr_t* arg_annotation_type = get_var_intent_and_annotation(x.m_args.m_args[i].m_annotation, s_intent);
3798+
ASR::ttype_t *arg_type = ast_expr_to_asr_type(x.base.base.loc, *arg_annotation_type);
37453799
// Set the function as generic if an argument is typed with a type parameter
37463800
if (ASRUtils::is_generic(*arg_type)) {
37473801
ASR::ttype_t* arg_type_type = ASRUtils::get_type_parameter(arg_type);
@@ -3766,12 +3820,13 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
37663820
}
37673821

37683822
std::string arg_s = arg;
3769-
37703823
ASR::expr_t *value = nullptr;
37713824
ASR::expr_t *init_expr = nullptr;
3772-
ASR::intentType s_intent = ASRUtils::intent_in;
3773-
if (ASRUtils::is_array(arg_type)) {
3774-
s_intent = ASRUtils::intent_inout;
3825+
if (s_intent == ASRUtils::intent_unspecified) {
3826+
s_intent = ASRUtils::intent_in;
3827+
if (ASRUtils::is_array(arg_type)) {
3828+
s_intent = ASRUtils::intent_inout;
3829+
}
37753830
}
37763831
ASR::storage_typeType storage_type =
37773832
ASR::storage_typeType::Default;
@@ -6125,8 +6180,10 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
61256180
);
61266181
throw SemanticAbort();
61276182
}
6128-
return ASR::make_CPtrToPointer_t(al, x.base.base.loc, cptr,
6129-
pptr, nullptr);
6183+
const Location& loc = x.base.base.loc;
6184+
fill_shape_and_lower_bound_for_CPtrToPointer();
6185+
return ASR::make_CPtrToPointer_t(al, loc, cptr,
6186+
pptr, target_shape, lower_bounds);
61306187
}
61316188

61326189
ASR::asr_t* create_PointerToCPtr(const AST::Call_t& x) {

src/runtime/lpython/lpython.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ def __call__(self, arg):
4444
return self._convert(arg)
4545

4646
def dataclass(arg):
47-
arg.__class_getitem__ = lambda self: None
47+
def __class_getitem__(key):
48+
return Array(arg, key)
49+
arg.__class_getitem__ = __class_getitem__
50+
4851
return py_dataclass(arg)
4952

5053
def is_ctypes_Structure(obj):
@@ -87,6 +90,18 @@ def __init__(self, type, dims):
8790
Union = ctypes.Union
8891
Pointer = PointerType("Pointer")
8992

93+
94+
class Intent:
95+
def __init__(self, type):
96+
self._type = type
97+
98+
def __getitem__(self, params):
99+
return params
100+
101+
In = Intent("In")
102+
Out = Intent("Out")
103+
InOut = Intent("InOut")
104+
90105
# Generics
91106

92107
class TypeVar():
@@ -258,6 +273,8 @@ def convert_type_to_ctype(arg):
258273
elif arg is None:
259274
raise NotImplementedError("Type cannot be None")
260275
elif isinstance(arg, Array):
276+
if is_dataclass(arg._type):
277+
return arg
261278
type = convert_type_to_ctype(arg._type)
262279
return ctypes.POINTER(type)
263280
elif is_dataclass(arg):
@@ -536,6 +553,8 @@ def __setattr__(self, name: str, value):
536553
def c_p_pointer(cptr, targettype):
537554
targettype_ptr = convert_type_to_ctype(targettype)
538555
if isinstance(targettype, Array):
556+
if py_is_dataclass(targettype._type):
557+
return ctypes.cast(cptr.value, ctypes.py_object).value
539558
newa = ctypes.cast(cptr, targettype_ptr)
540559
return newa
541560
else:

tests/intent_01.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@dataclass
2+
class Foo:
3+
p: i32
4+
5+
def f(x: i32, y: In[f64], z: InOut[list[u32]], w: Out[Foo[5]]):
6+
pass

tests/reference/asr-bindc_01-6d521a9.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-bindc_01-6d521a9.stdout",
9-
"stdout_hash": "d02c57ff6ddb41568c291b11a31301870bf2bc3a970461a71ec23a9d",
9+
"stdout_hash": "26baf870cb5fc3b568cb3d4bf45527713699c39609b6598186843330",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

tests/reference/asr-bindc_01-6d521a9.stdout

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
(Var 5 queries)
3737
(Var 5 x)
3838
()
39+
()
3940
)
4041
(Print
4142
()

tests/reference/asr-bindc_02-bc1a7ea.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-bindc_02-bc1a7ea.stdout",
9-
"stdout_hash": "a74aa56cff206d4ef8fb0766f1cf596c122255882a7df3f5e4fcf4e7",
9+
"stdout_hash": "dcf32037db14152961ae628f9687bfe7dfba3a34bb5a0e8da314fed1",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0

0 commit comments

Comments
 (0)