Skip to content

Commit d6e350e

Browse files
committed
Add class members
1 parent 7eb2bea commit d6e350e

File tree

7 files changed

+88
-27
lines changed

7 files changed

+88
-27
lines changed

Diff for: integration_tests/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,7 @@ RUN(NAME class_03 LABELS cpython llvm llvm_jit)
843843
RUN(NAME class_04 LABELS cpython llvm llvm_jit)
844844
RUN(NAME class_05 LABELS cpython llvm llvm_jit)
845845
RUN(NAME class_06 LABELS cpython llvm llvm_jit)
846+
RUN(NAME class_07 LABELS cpython llvm llvm_jit)
846847

847848

848849
# callback_04 is to test emulation. So just run with cpython

Diff for: integration_tests/class_07.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from lpython import i32
2+
3+
class MyClass:
4+
class_var: i32 = 42
5+
6+
def __init__(self: "MyClass", instance_value: i32):
7+
self.instance_var: i32 = instance_value
8+
9+
def main():
10+
assert MyClass.class_var == 42
11+
MyClass.class_var = 100
12+
assert MyClass.class_var == 100
13+
obj1: MyClass = MyClass(10)
14+
assert obj1.class_var == 100
15+
16+
if __name__ == '__main__':
17+
main()

Diff for: src/libasr/ASR.asdl

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ ttype
218218
cast_kind = RealToInteger | IntegerToReal | LogicalToReal | RealToReal | IntegerToInteger | RealToComplex | IntegerToComplex | IntegerToLogical | RealToLogical | CharacterToLogical | CharacterToInteger | CharacterToList | ComplexToLogical | ComplexToComplex | ComplexToReal | ComplexToInteger | LogicalToInteger | RealToCharacter | IntegerToCharacter | LogicalToCharacter | UnsignedIntegerToInteger | UnsignedIntegerToUnsignedInteger | UnsignedIntegerToReal | UnsignedIntegerToLogical | IntegerToUnsignedInteger | RealToUnsignedInteger | CPtrToUnsignedInteger | UnsignedIntegerToCPtr | IntegerToSymbolicExpression | ListToArray | DerivedToBase
219219
storage_type = Default | Save | Parameter
220220
access = Public | Private
221-
intent = Local | In | Out | InOut | ReturnVar | Unspecified
221+
intent = Local | In | Out | InOut | ReturnVar | ClassMember | Unspecified
222222
deftype = Implementation | Interface
223223
presence = Required | Optional
224224
abi = Source | LFortranModule | GFortranModule | BindC | BindPython | BindJS | Interactive | Intrinsic

Diff for: src/libasr/asr_utils.h

+1
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,7 @@ const ASR::intentType intent_local=ASR::intentType::Local; // local variable (no
18521852
const ASR::intentType intent_in =ASR::intentType::In; // dummy argument, intent(in)
18531853
const ASR::intentType intent_out =ASR::intentType::Out; // dummy argument, intent(out)
18541854
const ASR::intentType intent_inout=ASR::intentType::InOut; // dummy argument, intent(inout)
1855+
const ASR::intentType intent_classmember=ASR::intentType::ClassMember; // class variable
18551856
const ASR::intentType intent_return_var=ASR::intentType::ReturnVar; // return variable of a function
18561857
const ASR::intentType intent_unspecified=ASR::intentType::Unspecified; // dummy argument, ambiguous intent
18571858

Diff for: src/libasr/asr_verify.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
797797
s = ASRUtils::symbol_get_past_external(x.m_v);
798798
}
799799
require(is_a<Variable_t>(*s) || is_a<Function_t>(*s)
800-
|| is_a<ASR::EnumType_t>(*s) || is_a<ASR::ExternalSymbol_t>(*s),
800+
|| is_a<ASR::EnumType_t>(*s) || is_a<ASR::ExternalSymbol_t>(*s) || is_a<ASR::Struct_t>(*s),
801801
"Var_t::m_v " + x_mv_name + " does not point to a Variable_t, " \
802802
"Function_t, or EnumType_t (possibly behind ExternalSymbol_t)");
803803
require(symtab_in_scope(current_symtab, x.m_v),

Diff for: src/libasr/codegen/asr_to_llvm.cpp

+34-1
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,11 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
27322732
}
27332733
ASR::Variable_t* member = down_cast<ASR::Variable_t>(symbol_get_past_external(x.m_m));
27342734
std::string member_name = std::string(member->m_name);
2735+
if (member->m_intent == ASRUtils::intent_classmember) {
2736+
llvm::Constant *ptr = module->getNamedGlobal(member_name);
2737+
tmp = ptr;
2738+
return;
2739+
}
27352740
LCOMPILERS_ASSERT(current_der_type_name.size() != 0);
27362741
while( name2memidx[current_der_type_name].find(member_name) == name2memidx[current_der_type_name].end() ) {
27372742
if( dertype2parent.find(current_der_type_name) == dertype2parent.end() ) {
@@ -2763,6 +2768,24 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
27632768
}
27642769
}
27652770

2771+
2772+
void visit_StructStaticMember(const ASR::StructStaticMember_t& x) {
2773+
if (x.m_value) {
2774+
this->visit_expr_wrapper(x.m_value, true);
2775+
return;
2776+
}
2777+
2778+
ASR::Variable_t* member = down_cast<ASR::Variable_t>(symbol_get_past_external(x.m_m));
2779+
std::string member_name = std::string(member->m_name);
2780+
2781+
llvm::Constant *ptr = module->getNamedGlobal(member_name);
2782+
if (is_assignment_target) {
2783+
tmp = ptr;
2784+
return;
2785+
}
2786+
tmp = CreateLoad(ptr);
2787+
}
2788+
27662789
void visit_Variable(const ASR::Variable_t &x) {
27672790
if (compiler_options.interactive &&
27682791
std::strcmp(x.m_name, "_") == 0 &&
@@ -2782,7 +2805,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
27822805
// (global variable declared/initialized in this translation unit), or
27832806
// external (global variable not declared/initialized in this
27842807
// translation unit, just referenced).
2785-
LCOMPILERS_ASSERT(x.m_intent == intent_local || x.m_intent == ASRUtils::intent_unspecified
2808+
LCOMPILERS_ASSERT(x.m_intent == intent_local || x.m_intent == ASRUtils::intent_classmember || x.m_intent == ASRUtils::intent_unspecified
27862809
|| x.m_abi == ASR::abiType::Interactive);
27872810
bool external = (x.m_abi != ASR::abiType::Source);
27882811
llvm::Constant* init_value = nullptr;
@@ -3127,6 +3150,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
31273150
instantiate_function(*v);
31283151
}
31293152
}
3153+
for (size_t i = 0; i < x.n_members; i++) {
3154+
ASR::Variable_t *v = down_cast<ASR::Variable_t>(x.m_symtab->get_symbol(x.m_members[i]));
3155+
if (v->m_intent == ASRUtils::intent_classmember) {
3156+
v->m_name = s2c(al, mangle_prefix + v->m_name);
3157+
if (!v->m_symbolic_value)
3158+
v->m_symbolic_value = x.m_initializers[i].m_value;
3159+
visit_Variable(*v);
3160+
}
3161+
}
31303162
current_scope = current_scope_copy;
31313163
}
31323164

@@ -4956,6 +4988,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
49564988
x.m_target->type == ASR::exprType::StringItem ||
49574989
x.m_target->type == ASR::exprType::ArraySection ||
49584990
x.m_target->type == ASR::exprType::StructInstanceMember ||
4991+
x.m_target->type == ASR::exprType::StructStaticMember ||
49594992
x.m_target->type == ASR::exprType::ListItem ||
49604993
x.m_target->type == ASR::exprType::DictItem ||
49614994
x.m_target->type == ASR::exprType::UnionInstanceMember ) {

Diff for: src/lpython/semantics/python_ast_to_asr.cpp

+33-24
Original file line numberDiff line numberDiff line change
@@ -2669,9 +2669,9 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
26692669

26702670
void create_add_variable_to_scope(std::string& var_name,
26712671
ASR::ttype_t* type, const Location& loc, ASR::abiType abi,
2672-
ASR::storage_typeType storage_type=ASR::storage_typeType::Default) {
2672+
ASR::storage_typeType storage_type=ASR::storage_typeType::Default,
2673+
ASR::intentType s_intent = ASRUtils::intent_local) {
26732674

2674-
ASR::intentType s_intent = ASRUtils::intent_local;
26752675
ASR::abiType current_procedure_abi_type = abi;
26762676
ASR::accessType s_access = ASR::accessType::Public;
26772677
ASR::presenceType s_presence = ASR::presenceType::Required;
@@ -2891,7 +2891,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
28912891
ASR::expr_t* &init_expr,
28922892
bool wrap_derived_type_in_pointer=false,
28932893
ASR::abiType abi=ASR::abiType::Source,
2894-
bool inside_struct=false) {
2894+
bool inside_struct=false, bool inside_class=false) {
28952895
bool is_allocatable = false, is_const = false;
28962896
ASR::ttype_t *type = nullptr;
28972897
if( inside_struct ) {
@@ -2917,8 +2917,13 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
29172917
storage_type = ASR::storage_typeType::Parameter;
29182918
}
29192919

2920-
create_add_variable_to_scope(var_name, type,
2921-
x.base.base.loc, abi, storage_type);
2920+
if ( inside_class ) {
2921+
create_add_variable_to_scope(var_name, type,
2922+
x.base.base.loc, abi, storage_type, ASRUtils::intent_classmember);
2923+
} else {
2924+
create_add_variable_to_scope(var_name, type,
2925+
x.base.base.loc, abi, storage_type);
2926+
}
29222927

29232928
ASR::expr_t* assign_asr_target_copy = assign_asr_target;
29242929
this->visit_expr(*x.m_target);
@@ -3082,7 +3087,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
30823087
ASR::ttype_t* i64_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 8));
30833088
init_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, x.base.base.loc, -1, i64_type));
30843089
}
3085-
visit_AnnAssignUtil(*ann_assign, var_name, init_expr, false, abi, true);
3090+
visit_AnnAssignUtil(*ann_assign, var_name, init_expr, false, abi, true, is_class_scope);
30863091
ASR::symbol_t* var_sym = current_scope->resolve_symbol(var_name);
30873092
ASR::call_arg_t c_arg;
30883093
c_arg.loc = var_sym->base.loc;
@@ -5425,20 +5430,22 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
54255430
throw SemanticError("Variable: '" + std::string(n->m_id) + "' is not declared",
54265431
x->base.loc);
54275432
}
5428-
ASR::Variable_t* v = ASR::down_cast<ASR::Variable_t>(s);
5429-
if (v->m_intent == ASR::intentType::In) {
5430-
std::string msg = "Hint: create a new local variable with a different name";
5431-
if (ASRUtils::is_aggregate_type(v->m_type)) {
5432-
msg = "Use InOut[" + ASRUtils::type_to_str_python(v->m_type) + "] to allow assignment";
5433+
if (ASR::is_a<ASR::Variable_t>(*s)) {
5434+
ASR::Variable_t* v = ASR::down_cast<ASR::Variable_t>(s);
5435+
if (v->m_intent == ASR::intentType::In) {
5436+
std::string msg = "Hint: create a new local variable with a different name";
5437+
if (ASRUtils::is_aggregate_type(v->m_type)) {
5438+
msg = "Use InOut[" + ASRUtils::type_to_str_python(v->m_type) + "] to allow assignment";
5439+
}
5440+
diag.add(diag::Diagnostic(
5441+
"Assignment to an input function parameter `"
5442+
+ std::string(v->m_name) + "` is not allowed",
5443+
diag::Level::Error, diag::Stage::Semantic, {
5444+
diag::Label(msg, {x->base.loc})
5445+
})
5446+
);
5447+
throw SemanticAbort();
54335448
}
5434-
diag.add(diag::Diagnostic(
5435-
"Assignment to an input function parameter `"
5436-
+ std::string(v->m_name) + "` is not allowed",
5437-
diag::Level::Error, diag::Stage::Semantic, {
5438-
diag::Label(msg, {x->base.loc})
5439-
})
5440-
);
5441-
throw SemanticAbort();
54425449
}
54435450
return true;
54445451
} else if (AST::is_a<AST::Subscript_t>(*x)) {
@@ -5583,15 +5590,17 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
55835590
AST::Attribute_t *attr = AST::down_cast<AST::Attribute_t>(x.m_targets[i]);
55845591
if (AST::is_a<AST::Name_t>(*attr->m_value)) {
55855592
std::string name = AST::down_cast<AST::Name_t>(attr->m_value)->m_id;
5586-
ASR::symbol_t *s = current_scope->get_symbol(name);
5593+
ASR::symbol_t *s = current_scope->resolve_symbol(name);
55875594
if (!s) {
55885595
throw SemanticError("Variable: '" + name + "' is not declared",
55895596
x.base.base.loc);
55905597
}
5591-
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(s);
5592-
ASR::ttype_t *type = v->m_type;
5593-
if (ASRUtils::is_immutable(type)) {
5594-
throw SemanticError("readonly attribute", x.base.base.loc);
5598+
if (ASR::is_a<ASR::Variable_t>(*s)) {
5599+
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(s);
5600+
ASR::ttype_t *type = v->m_type;
5601+
if (ASRUtils::is_immutable(type)) {
5602+
throw SemanticError("readonly attribute", x.base.base.loc);
5603+
}
55955604
}
55965605
}
55975606
}

0 commit comments

Comments
 (0)