22
22
#include < lpython/utils.h>
23
23
#include < lpython/semantics/semantic_exception.h>
24
24
#include < lpython/python_serialization.h>
25
+ #include < lpython/semantics/python_comptime_eval.h>
25
26
26
27
27
28
namespace LFortran ::Python {
@@ -147,11 +148,14 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
147
148
ASR::asr_t *tmp;
148
149
Allocator &al;
149
150
SymbolTable *current_scope;
151
+ // The current_module contains the current module that is being visited;
152
+ // this is used to append to the module dependencies if needed
150
153
ASR::Module_t *current_module = nullptr ;
151
154
Vec<char *> current_module_dependencies;
152
155
// True for the main module, false for every other one
153
156
// The main module is stored directly in TranslationUnit, other modules are Modules
154
157
bool main_module;
158
+ PythonIntrinsicProcedures intrinsic_procedures;
155
159
156
160
CommonVisitor (Allocator &al, SymbolTable *symbol_table,
157
161
diag::Diagnostics &diagnostics, bool main_module)
@@ -178,6 +182,72 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
178
182
return ASR::make_Var_t (al, loc, v);
179
183
}
180
184
185
+ ASR::symbol_t * resolve_intrinsic_function (const Location &loc, const std::string &remote_sym) {
186
+ LFORTRAN_ASSERT (intrinsic_procedures.is_intrinsic (remote_sym))
187
+ std::string module_name = intrinsic_procedures.get_module (remote_sym, loc);
188
+
189
+ SymbolTable *tu_symtab = ASRUtils::get_tu_symtab (current_scope);
190
+ std::string rl_path = get_runtime_library_dir ();
191
+ bool ltypes;
192
+ ASR::Module_t *m = load_module (al, tu_symtab, module_name,
193
+ loc, true , rl_path,
194
+ ltypes,
195
+ [&](const std::string &msg, const Location &loc) { throw SemanticError (msg, loc); }
196
+ );
197
+ LFORTRAN_ASSERT (!ltypes)
198
+
199
+ ASR::symbol_t *t = m->m_symtab ->resolve_symbol (remote_sym);
200
+ if (!t) {
201
+ throw SemanticError (" The symbol '" + remote_sym
202
+ + " ' not found in the module '" + module_name + " '" ,
203
+ loc);
204
+ } else if (! (ASR::is_a<ASR::GenericProcedure_t>(*t)
205
+ || ASR::is_a<ASR::Function_t>(*t)
206
+ || ASR::is_a<ASR::Subroutine_t>(*t))) {
207
+ throw SemanticError (" The symbol '" + remote_sym
208
+ + " ' found in the module '" + module_name + " ', "
209
+ + " but it is not a function, subroutine or a generic procedure." ,
210
+ loc);
211
+ }
212
+ char *fn_name = ASRUtils::symbol_name (t);
213
+ ASR::asr_t *fn = ASR::make_ExternalSymbol_t (
214
+ al, t->base .loc ,
215
+ /* a_symtab */ current_scope,
216
+ /* a_name */ fn_name,
217
+ t,
218
+ m->m_name , nullptr , 0 , fn_name,
219
+ ASR::accessType::Private
220
+ );
221
+ std::string sym = fn_name;
222
+
223
+ current_scope->scope [sym] = ASR::down_cast<ASR::symbol_t >(fn);
224
+ ASR::symbol_t *v = ASR::down_cast<ASR::symbol_t >(fn);
225
+
226
+ // Now we need to add the module `m` with the intrinsic function
227
+ // into the current module dependencies
228
+ if (current_module) {
229
+ // We are in body visitor, the module is already constructed
230
+ // and available as current_module.
231
+ // Add the module `m` to current module dependencies
232
+ Vec<char *> vec;
233
+ vec.from_pointer_n_copy (al, current_module->m_dependencies ,
234
+ current_module->n_dependencies );
235
+ if (!present (vec, m->m_name )) {
236
+ vec.push_back (al, m->m_name );
237
+ current_module->m_dependencies = vec.p ;
238
+ current_module->n_dependencies = vec.size ();
239
+ }
240
+ } else {
241
+ // We are in the symtab visitor or body visitor and we are
242
+ // constructing a module, so current_module is not available yet
243
+ // (the current_module_dependencies is not used in body visitor)
244
+ if (!present (current_module_dependencies, m->m_name )) {
245
+ current_module_dependencies.push_back (al, m->m_name );
246
+ }
247
+ }
248
+ return v;
249
+ }
250
+
181
251
// Convert Python AST type annotation to an ASR type
182
252
// Examples:
183
253
// i32, i64, f32, f64
@@ -1981,6 +2051,18 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
1981
2051
1982
2052
1983
2053
if (!s) {
2054
+ if (intrinsic_procedures.is_intrinsic (call_name)) {
2055
+ s = resolve_intrinsic_function (x.base .base .loc , call_name);
2056
+ } else {
2057
+ // TODO: We need to port all functions below to the intrinsic functions file
2058
+ // Then we can uncomment this error message:
2059
+ /*
2060
+ throw SemanticError("The function '" + call_name + "' is not declared and not intrinsic",
2061
+ x.base.base.loc);
2062
+ }
2063
+ if (false) {
2064
+ */
2065
+ // This will all be removed once we port it to intrinsic functions
1984
2066
// Intrinsic functions
1985
2067
if (call_name == " size" ) {
1986
2068
// TODO: size should be part of ASR. That way
@@ -2481,21 +2563,22 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2481
2563
throw SemanticError (" Function '" + call_name + " ' is not declared and not intrinsic" ,
2482
2564
x.base .base .loc );
2483
2565
}
2566
+ } // end of "comment"
2484
2567
}
2485
2568
2486
- if (!s) {
2487
- throw SemanticError (" Function '" + call_name + " ' is not declared" ,
2488
- x.base .base .loc );
2489
- }
2490
2569
// handling ExternalSymbol
2491
2570
ASR::symbol_t *stemp = s;
2492
2571
s = ASRUtils::symbol_get_past_external (s);
2493
2572
2494
2573
if (ASR::is_a<ASR::Function_t>(*s)) {
2495
2574
ASR::Function_t *func = ASR::down_cast<ASR::Function_t>(s);
2496
2575
ASR::ttype_t *a_type = ASRUtils::expr_type (func->m_return_var );
2576
+ ASR::expr_t *value = nullptr ;
2577
+ if (ASRUtils::is_intrinsic_function2 (func)) {
2578
+ value = intrinsic_procedures.comptime_eval (call_name, al, x.base .base .loc , args);
2579
+ }
2497
2580
tmp = ASR::make_FunctionCall_t (al, x.base .base .loc , stemp,
2498
- nullptr , args.p , args.size (), nullptr , 0 , a_type, nullptr , nullptr );
2581
+ nullptr , args.p , args.size (), nullptr , 0 , a_type, value , nullptr );
2499
2582
} else if (ASR::is_a<ASR::Subroutine_t>(*s)) {
2500
2583
tmp = ASR::make_SubroutineCall_t (al, x.base .base .loc , stemp,
2501
2584
nullptr , args.p , args.size (), nullptr );
0 commit comments