18
18
#include < libasr/utils.h>
19
19
#include < libasr/pass/global_stmts_program.h>
20
20
#include < libasr/pass/instantiate_template.h>
21
+ #include < libasr/modfile.h>
21
22
22
23
#include < lpython/python_ast.h>
23
24
#include < lpython/semantics/python_ast_to_asr.h>
27
28
#include < lpython/semantics/python_comptime_eval.h>
28
29
#include < lpython/semantics/python_attribute_eval.h>
29
30
#include < lpython/parser/parser.h>
31
+ #include < libasr/serialization.h>
30
32
31
33
32
34
namespace LFortran ::LPython {
@@ -150,13 +152,30 @@ namespace CastingUtil {
150
152
}
151
153
}
152
154
155
+ int save_pyc_files (const LFortran::ASR::TranslationUnit_t &u,
156
+ std::string infile) {
157
+ LFORTRAN_ASSERT (LFortran::asr_verify (u));
158
+ std::string modfile_binary = LFortran::save_pycfile (u);
159
+
160
+ while ( infile.back () != ' .' ) {
161
+ infile.pop_back ();
162
+ }
163
+ std::string modfile = infile + " pyc" ;
164
+ {
165
+ std::ofstream out;
166
+ out.open (modfile, std::ofstream::out | std::ofstream::binary);
167
+ out << modfile_binary;
168
+ }
169
+ return 0 ;
170
+ }
171
+
153
172
// Does a CPython style lookup for a module:
154
173
// * First the current directory (this is incorrect, we need to do it relative to the current file)
155
174
// * Then the LPython runtime directory
156
175
LFortran::Result<std::string> get_full_path (const std::string &filename,
157
- const std::string &runtime_library_dir, bool <ypes) {
176
+ const std::string &runtime_library_dir, std::string& input,
177
+ bool <ypes) {
158
178
ltypes = false ;
159
- std::string input;
160
179
bool status = read_file (filename, input);
161
180
if (status) {
162
181
return filename;
@@ -176,8 +195,8 @@ LFortran::Result<std::string> get_full_path(const std::string &filename,
176
195
} else {
177
196
return LFortran::Error ();
178
197
}
179
- } else if (filename == " numpy.py" ) {
180
- filename_intrinsic = runtime_library_dir + " /lpython_intrinsic_numpy.py " ;
198
+ } else if (startswith ( filename, " numpy.py" ) ) {
199
+ filename_intrinsic = runtime_library_dir + " /lpython_intrinsic_ " + filename ;
181
200
status = read_file (filename_intrinsic, input);
182
201
if (status) {
183
202
return filename_intrinsic;
@@ -191,6 +210,54 @@ LFortran::Result<std::string> get_full_path(const std::string &filename,
191
210
}
192
211
}
193
212
213
+ bool set_module_path (std::string infile0, std::vector<std::string> &rl_path,
214
+ std::string& infile, std::string& path_used, std::string& input,
215
+ bool & ltypes) {
216
+ for (auto path: rl_path) {
217
+ Result<std::string> rinfile = get_full_path (infile0, path, input, ltypes);
218
+ if (rinfile.ok ) {
219
+ infile = rinfile.result ;
220
+ path_used = path;
221
+ return true ;
222
+ }
223
+ }
224
+ return false ;
225
+ }
226
+
227
+ ASR::TranslationUnit_t* compile_module_till_asr (Allocator& al,
228
+ std::vector<std::string> &rl_path, std::string infile,
229
+ const Location &loc,
230
+ const std::function<void (const std::string &, const Location &)> err) {
231
+ // TODO: diagnostic should be an argument to this function
232
+ diag::Diagnostics diagnostics;
233
+ Result<AST::ast_t *> r = parse_python_file (al, rl_path[0 ], infile,
234
+ diagnostics, false );
235
+ if (!r.ok ) {
236
+ err (" The file '" + infile + " ' failed to parse" , loc);
237
+ }
238
+ LFortran::LPython::AST::ast_t * ast = r.result ;
239
+
240
+ // Convert the module from AST to ASR
241
+ LFortran::LocationManager lm;
242
+ lm.in_filename = infile;
243
+ Result<ASR::TranslationUnit_t*> r2 = python_ast_to_asr (al, *ast,
244
+ diagnostics, false , true , false , infile);
245
+ // TODO: Uncomment once a check is added for ensuring
246
+ // that module.py file hasn't changed between
247
+ // builds.
248
+ // save_pyc_files(*r2.result, infile + "c");
249
+ std::string input;
250
+ read_file (infile, input);
251
+ CompilerOptions compiler_options;
252
+ std::cerr << diagnostics.render (input, lm, compiler_options);
253
+ if (!r2.ok ) {
254
+ LFORTRAN_ASSERT (diagnostics.has_error ())
255
+ return nullptr ; // Error
256
+ }
257
+
258
+ return r2.result ;
259
+ }
260
+
194
261
ASR::Module_t* load_module (Allocator &al, SymbolTable *symtab,
195
262
const std::string &module_name,
196
263
const Location &loc, bool intrinsic,
@@ -214,45 +281,32 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab,
214
281
215
282
// Parse the module `module_name`.py to AST
216
283
std::string infile0 = module_name + " .py" ;
217
- bool found = false ;
284
+ std::string infile0c = infile0 + " c " ;
218
285
std::string path_used = " " , infile;
219
- for (auto path: rl_path) {
220
- Result<std::string> rinfile = get_full_path (infile0, path, ltypes);
221
- if (rinfile.ok ) {
222
- found = true ;
223
- infile = rinfile.result ;
224
- path_used = path;
225
- break ;
226
- }
286
+ bool compile_module = true ;
287
+ ASR::TranslationUnit_t* mod1 = nullptr ;
288
+ std::string input;
289
+ bool found = set_module_path (infile0c, rl_path, infile,
290
+ path_used, input, ltypes);
291
+ if ( !found ) {
292
+ input.clear ();
293
+ found = set_module_path (infile0, rl_path, infile,
294
+ path_used, input, ltypes);
295
+ } else {
296
+ mod1 = load_pycfile (al, input, false );
297
+ fix_external_symbols (*mod1, *ASRUtils::get_tu_symtab (symtab));
298
+ LFORTRAN_ASSERT (asr_verify (*mod1));
299
+ compile_module = false ;
227
300
}
301
+
228
302
if (!found) {
229
303
err (" Could not find the module '" + infile0 + " '" , loc);
230
304
}
231
305
if (ltypes) return nullptr ;
232
306
233
- // TODO: diagnostic should be an argument to this function
234
- diag::Diagnostics diagnostics;
235
- Result<AST::ast_t *> r = parse_python_file (al, rl_path[0 ], infile,
236
- diagnostics, false );
237
- if (!r.ok ) {
238
- err (" The file '" + infile + " ' failed to parse" , loc);
239
- }
240
- LFortran::LPython::AST::ast_t * ast = r.result ;
241
-
242
- // Convert the module from AST to ASR
243
- LFortran::LocationManager lm;
244
- lm.in_filename = infile;
245
- Result<ASR::TranslationUnit_t*> r2 = python_ast_to_asr (al, *ast,
246
- diagnostics, false , true , false , infile);
247
- std::string input;
248
- read_file (infile, input);
249
- CompilerOptions compiler_options;
250
- std::cerr << diagnostics.render (input, lm, compiler_options);
251
- if (!r2.ok ) {
252
- LFORTRAN_ASSERT (diagnostics.has_error ())
253
- return nullptr ; // Error
307
+ if ( compile_module ) {
308
+ mod1 = compile_module_till_asr (al, rl_path, infile, loc, err);
254
309
}
255
- ASR::TranslationUnit_t* mod1 = r2.result ;
256
310
257
311
// insert into `symtab`
258
312
std::vector<std::pair<std::string, ASR::Module_t*>> children_modules;
0 commit comments