Skip to content

Commit eb8017e

Browse files
committed
Following changes have been made,
1. Only those variables which are constant and have a compile time initialisation expression will have non-nullptr values for m_symbolic_value and m_value 2. Rest all will be converted to assignment statements.
1 parent 57699a9 commit eb8017e

File tree

8 files changed

+94
-46
lines changed

8 files changed

+94
-46
lines changed

integration_tests/nrp/nr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ltypes import i32, f64
1+
from lpython import i32, f64
22

33

44
def func(x: f64, c: f64) -> f64:

integration_tests/test_package_01.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from nrp import newton_raphson
2-
from ltypes import f64, i32
2+
from lpython import f64, i32
33

44

55
def check():

integration_tests/variable_decl_01.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from lpython import i32, i64
1+
from lpython import i32, i64, Const
22
from numpy import empty, int64
33

44
def f(n: i32, m: i32):
5-
l: i32 = 2
5+
l: Const[i32] = 2
66
a: i64[n, m, l] = empty((n, m, l), dtype=int64)
77
i: i32; j: i32; k: i32;
88
for i in range(n):

src/libasr/asr_utils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,8 +963,8 @@ ASR::asr_t* make_Cast_t_value(Allocator &al, const Location &a_loc,
963963
double_value, 0, a_type));
964964
} else if (a_kind == ASR::cast_kindType::IntegerToReal) {
965965
// TODO: Clashes with the pow functions
966-
// int64_t value = ASR::down_cast<ASR::ConstantInteger_t>(ASRUtils::expr_value(a_arg))->m_n;
967-
// value = ASR::down_cast<ASR::expr_t>(ASR::make_ConstantReal_t(al, a_loc, (double)v, a_type));
966+
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(ASRUtils::expr_value(a_arg))->m_n;
967+
value = ASR::down_cast<ASR::expr_t>(ASR::make_RealConstant_t(al, a_loc, (double)int_value, a_type));
968968
} else if (a_kind == ASR::cast_kindType::IntegerToComplex) {
969969
int64_t int_value = ASR::down_cast<ASR::IntegerConstant_t>(
970970
ASRUtils::expr_value(a_arg))->m_n;

src/libasr/asr_verify.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,15 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
516516
"Variable::m_parent_symtab must be present in the ASR ("
517517
+ std::string(x.m_name) + ")");
518518

519+
if( symtab->parent == nullptr ) {
520+
// For nowRestrict this check only to variables which are present
521+
// inside symbols which have a body.
522+
require( (x.m_symbolic_value == nullptr && x.m_value == nullptr) ||
523+
(x.m_symbolic_value != nullptr && x.m_value != nullptr),
524+
"Initialisation of " + std::string(x.m_name) +
525+
" must reduce to a compile time constant.");
526+
}
527+
519528
if (x.m_symbolic_value)
520529
visit_expr(*x.m_symbolic_value);
521530
visit_ttype(*x.m_type);

src/libasr/pass/inline_function_calls.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -294,18 +294,22 @@ class InlineFunctionCallVisitor : public PassUtils::PassVisitor<InlineFunctionCa
294294
break;
295295
}
296296
ASR::ttype_t* local_var_type = func_var->m_type;
297+
if( ASR::is_a<ASR::Const_t>(*local_var_type) ) {
298+
local_var_type = ASR::down_cast<ASR::Const_t>(local_var_type)->m_type;
299+
}
300+
LCOMPILERS_ASSERT(!ASR::is_a<ASR::Const_t>(*local_var_type));
297301
ASR::symbol_t* local_var = (ASR::symbol_t*) ASR::make_Variable_t(
298-
al, func_var->base.base.loc, current_scope,
299-
s2c(al, local_var_name), nullptr, 0, ASR::intentType::Local,
300-
nullptr, nullptr, ASR::storage_typeType::Default,
301-
local_var_type, ASR::abiType::Source, ASR::accessType::Public,
302-
ASR::presenceType::Required, false);
302+
al, func_var->base.base.loc, current_scope,
303+
s2c(al, local_var_name), nullptr, 0, ASR::intentType::Local,
304+
nullptr, nullptr, ASR::storage_typeType::Default,
305+
local_var_type, ASR::abiType::Source, ASR::accessType::Public,
306+
ASR::presenceType::Required, false);
303307
current_scope->add_symbol(local_var_name, local_var);
304308
arg2value[func_var_name] = local_var;
305-
if( m_symbolic_value && !ASR::is_a<ASR::Const_t>(*local_var_type) ) {
309+
if( m_symbolic_value ) {
306310
exprs_to_be_visited.push_back(std::make_pair(m_symbolic_value, local_var));
307311
}
308-
if( m_value && !ASR::is_a<ASR::Const_t>(*local_var_type) ) {
312+
if( m_value ) {
309313
exprs_to_be_visited.push_back(std::make_pair(m_value, local_var));
310314
}
311315
}

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,20 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
13761376
return t;
13771377
}
13781378

1379+
bool contains_local_variable(ASR::expr_t* value) {
1380+
if( ASR::is_a<ASR::Var_t>(*value) ) {
1381+
ASR::Var_t* var_value = ASR::down_cast<ASR::Var_t>(value);
1382+
ASR::symbol_t* var_value_sym = var_value->m_v;
1383+
ASR::Variable_t* var_value_variable = ASR::down_cast<ASR::Variable_t>(
1384+
ASRUtils::symbol_get_past_external(var_value_sym));
1385+
return var_value_variable->m_intent == ASR::intentType::Local;
1386+
}
1387+
1388+
// TODO: Let any other expression pass through
1389+
// Will be handled later
1390+
return false;
1391+
}
1392+
13791393
void fill_dims_for_asr_type(Vec<ASR::dimension_t>& dims,
13801394
ASR::expr_t* value, const Location& loc) {
13811395
ASR::dimension_t dim;
@@ -1388,8 +1402,13 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
13881402
ASR::expr_t* zero = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, 0, itype));
13891403
ASR::expr_t* comptime_val = nullptr;
13901404
int64_t value_int = -1;
1391-
ASRUtils::extract_value(ASRUtils::expr_value(value), value_int);
1392-
if( value_int != -1 ) {
1405+
if( !ASRUtils::extract_value(ASRUtils::expr_value(value), value_int) &&
1406+
contains_local_variable(value) ) {
1407+
throw SemanticError("Only those local variables which can be reduced to compile "
1408+
"time constant should be used in dimensions of an array.",
1409+
value->base.loc);
1410+
}
1411+
if (value_int != -1) {
13931412
comptime_val = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, loc, value_int - 1, itype));
13941413
}
13951414
dim.m_start = zero;
@@ -2184,12 +2203,20 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
21842203
}
21852204

21862205
void create_add_variable_to_scope(std::string& var_name, ASR::expr_t* init_expr,
2187-
ASR::expr_t* value, ASR::ttype_t* type,
2188-
const Location& loc, ASR::abiType abi) {
2189-
if( ASR::is_a<ASR::Const_t>(*type) && !init_expr ) {
2206+
ASR::ttype_t* type, const Location& loc, ASR::abiType abi) {
2207+
2208+
ASR::expr_t* value = nullptr;
2209+
if( init_expr ) {
2210+
value = ASRUtils::expr_value(init_expr);
2211+
}
2212+
bool is_runtime_expression = !ASRUtils::is_value_constant(value);
2213+
bool is_variable_const = ASR::is_a<ASR::Const_t>(*type);
2214+
2215+
if( is_variable_const && !init_expr ) {
21902216
throw SemanticError("Constant variable " + var_name +
21912217
" is not initialised at declaration.", loc);
21922218
}
2219+
21932220
ASR::intentType s_intent = ASRUtils::intent_local;
21942221
ASR::storage_typeType storage_type =
21952222
ASR::storage_typeType::Default;
@@ -2210,24 +2237,30 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
22102237
current_procedure_abi_type, s_access, s_presence,
22112238
value_attr);
22122239
ASR::symbol_t* v_sym = ASR::down_cast<ASR::symbol_t>(v);
2240+
ASR::Variable_t* v_variable = ASR::down_cast<ASR::Variable_t>(v_sym);
22132241

2214-
if( init_expr && current_body) {
2242+
if( init_expr && current_body &&
2243+
(is_runtime_expression || !is_variable_const)) {
22152244
ASR::expr_t* v_expr = ASRUtils::EXPR(ASR::make_Var_t(al, loc, v_sym));
22162245
cast_helper(v_expr, init_expr, true);
22172246
ASR::asr_t* assign = ASR::make_Assignment_t(al, loc, v_expr,
22182247
init_expr, nullptr);
22192248
current_body->push_back(al, ASRUtils::STMT(assign));
2220-
ASR::Variable_t* v_variable = ASR::down_cast<ASR::Variable_t>(v_sym);
2221-
if( !ASR::is_a<ASR::Const_t>(*type) &&
2222-
ASRUtils::is_aggregate_type(type) ) {
2223-
v_variable->m_symbolic_value = nullptr;
2224-
v_variable->m_value = nullptr;
2225-
Vec<char*> variable_dependencies_vec;
2226-
variable_dependencies_vec.reserve(al, 1);
2227-
ASRUtils::collect_variable_dependencies(al, variable_dependencies_vec, type);
2228-
v_variable->m_dependencies = variable_dependencies_vec.p;
2229-
v_variable->n_dependencies = variable_dependencies_vec.size();
2230-
}
2249+
2250+
v_variable->m_symbolic_value = nullptr;
2251+
v_variable->m_value = nullptr;
2252+
Vec<char*> variable_dependencies_vec;
2253+
variable_dependencies_vec.reserve(al, 1);
2254+
ASRUtils::collect_variable_dependencies(al, variable_dependencies_vec, type);
2255+
v_variable->m_dependencies = variable_dependencies_vec.p;
2256+
v_variable->n_dependencies = variable_dependencies_vec.size();
2257+
}
2258+
2259+
// Restrict this check only to symbols which have a body.
2260+
if( !((v_variable->m_symbolic_value == nullptr && v_variable->m_value == nullptr) ||
2261+
(v_variable->m_symbolic_value != nullptr && v_variable->m_value != nullptr)) &&
2262+
current_body ) {
2263+
throw SemanticError("Initialisation of " + var_name + " must reduce to a compile time constant.", loc);
22312264
}
22322265
current_scope->add_symbol(var_name, v_sym);
22332266
}
@@ -2275,7 +2308,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
22752308
this->visit_expr(*x.m_value);
22762309
}
22772310
if( is_c_p_pointer_call ) {
2278-
create_add_variable_to_scope(var_name, nullptr, nullptr, type,
2311+
create_add_variable_to_scope(var_name, nullptr, type,
22792312
x.base.base.loc, abi);
22802313
AST::Call_t* c_p_pointer_call = AST::down_cast<AST::Call_t>(x.m_value);
22812314
AST::expr_t* cptr = c_p_pointer_call->m_args[0];
@@ -2305,17 +2338,13 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
23052338
throw SemanticAbort();
23062339
}
23072340
init_expr = value;
2308-
value = nullptr;
2309-
if( ASR::is_a<ASR::Const_t>(*type) ) {
2310-
value = ASRUtils::expr_value(init_expr);
2311-
}
23122341
}
23132342
} else {
23142343
cast_helper(type, init_expr, init_expr->base.loc);
23152344
}
23162345

23172346
if( !is_c_p_pointer_call ) {
2318-
create_add_variable_to_scope(var_name, init_expr, value, type,
2347+
create_add_variable_to_scope(var_name, init_expr, type,
23192348
x.base.base.loc, abi);
23202349
}
23212350

@@ -5685,7 +5714,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
56855714
fn_args.push_back(al, sub);
56865715
} else if (attr_name == "endswith") {
56875716
/*
5688-
str.endswith(suffix) ---->
5717+
str.endswith(suffix) ---->
56895718
Return True if the string ends with the specified suffix, otherwise return False.
56905719
56915720
arg_sub: Substring argument provided inside endswith() function
@@ -5907,8 +5936,8 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
59075936
}
59085937
return;
59095938
} else if (attr_name == "endswith") {
5910-
/*
5911-
str.endswith(suffix) ---->
5939+
/*
5940+
str.endswith(suffix) ---->
59125941
Return True if the string ends with the specified suffix, otherwise return False.
59135942
*/
59145943

@@ -5921,23 +5950,23 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
59215950
if (!ASRUtils::is_character(*arg_suffix_type)) {
59225951
throw SemanticError("str.endswith() takes one arguments of type: str", arg_suffix->base.loc);
59235952
}
5924-
5953+
59255954
if (ASRUtils::expr_value(arg_suffix) != nullptr) {
59265955
/*
59275956
Invoked when Suffix argument is provided as a constant string
59285957
*/
59295958
ASR::StringConstant_t* suffix_constant = ASR::down_cast<ASR::StringConstant_t>(arg_suffix);
59305959
std::string suffix = suffix_constant->m_s;
5931-
5960+
59325961
bool res = true;
5933-
if (suffix.size() > s_var.size())
5962+
if (suffix.size() > s_var.size())
59345963
res = false;
5935-
else
5964+
else
59365965
res = std::equal(suffix.rbegin(), suffix.rend(), s_var.rbegin());
5937-
5938-
tmp = ASR::make_LogicalConstant_t(al, loc, res,
5966+
5967+
tmp = ASR::make_LogicalConstant_t(al, loc, res,
59395968
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4, nullptr, 0)));
5940-
5969+
59415970
} else {
59425971
/*
59435972
Invoked when Suffix argument is provided as a variable

src/lpython/semantics/python_intrinsic_eval.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ struct IntrinsicNodeHandler {
110110
} else if (ASRUtils::is_integer(*type)) {
111111
// int() returns a 64-bit integer
112112
if (ASRUtils::extract_kind_from_ttype_t(type) != 8) {
113+
if (ASRUtils::expr_value(arg) != nullptr) {
114+
int64_t ival = ASR::down_cast<ASR::IntegerConstant_t>(
115+
ASRUtils::expr_value(arg))->m_n;
116+
value = ASR::down_cast<ASR::expr_t>(make_IntegerConstant_t(al,
117+
loc, ival, to_type));
118+
}
113119
return (ASR::asr_t *)ASR::down_cast<ASR::expr_t>(ASR::make_Cast_t(
114120
al, loc, arg, ASR::cast_kindType::IntegerToInteger,
115121
to_type, value));

0 commit comments

Comments
 (0)