Skip to content

Commit 8a609bf

Browse files
committed
Added save_pyc_files for saving LPython generated ASR (with c and disable_main options)
1 parent 2387c68 commit 8a609bf

File tree

2 files changed

+93
-36
lines changed

2 files changed

+93
-36
lines changed

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 89 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <libasr/utils.h>
1919
#include <libasr/pass/global_stmts_program.h>
2020
#include <libasr/pass/instantiate_template.h>
21+
#include <libasr/modfile.h>
2122

2223
#include <lpython/python_ast.h>
2324
#include <lpython/semantics/python_ast_to_asr.h>
@@ -27,6 +28,7 @@
2728
#include <lpython/semantics/python_comptime_eval.h>
2829
#include <lpython/semantics/python_attribute_eval.h>
2930
#include <lpython/parser/parser.h>
31+
#include <libasr/serialization.h>
3032

3133

3234
namespace LFortran::LPython {
@@ -150,13 +152,30 @@ namespace CastingUtil {
150152
}
151153
}
152154

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+
153172
// Does a CPython style lookup for a module:
154173
// * First the current directory (this is incorrect, we need to do it relative to the current file)
155174
// * Then the LPython runtime directory
156175
LFortran::Result<std::string> get_full_path(const std::string &filename,
157-
const std::string &runtime_library_dir, bool &ltypes) {
176+
const std::string &runtime_library_dir, std::string& input,
177+
bool &ltypes) {
158178
ltypes = false;
159-
std::string input;
160179
bool status = read_file(filename, input);
161180
if (status) {
162181
return filename;
@@ -176,8 +195,8 @@ LFortran::Result<std::string> get_full_path(const std::string &filename,
176195
} else {
177196
return LFortran::Error();
178197
}
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;
181200
status = read_file(filename_intrinsic, input);
182201
if (status) {
183202
return filename_intrinsic;
@@ -191,6 +210,54 @@ LFortran::Result<std::string> get_full_path(const std::string &filename,
191210
}
192211
}
193212

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+
194261
ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab,
195262
const std::string &module_name,
196263
const Location &loc, bool intrinsic,
@@ -214,45 +281,32 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab,
214281

215282
// Parse the module `module_name`.py to AST
216283
std::string infile0 = module_name + ".py";
217-
bool found = false;
284+
std::string infile0c = infile0 + "c";
218285
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;
227300
}
301+
228302
if (!found) {
229303
err("Could not find the module '" + infile0 + "'", loc);
230304
}
231305
if (ltypes) return nullptr;
232306

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);
254309
}
255-
ASR::TranslationUnit_t* mod1 = r2.result;
256310

257311
// insert into `symtab`
258312
std::vector<std::pair<std::string, ASR::Module_t*>> children_modules;

src/lpython/semantics/python_ast_to_asr.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
#include <libasr/asr.h>
66

77
namespace LFortran::LPython {
8-
8+
99
std::string pickle_python(AST::ast_t &ast, bool colors=false, bool indent=false);
1010
std::string pickle_tree_python(AST::ast_t &ast, bool colors=true);
1111
Result<ASR::TranslationUnit_t*> python_ast_to_asr(Allocator &al,
1212
LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics,
1313
bool main_module, bool disable_main, bool symtab_only, std::string file_path);
1414

15+
int save_pyc_files(const LFortran::ASR::TranslationUnit_t &u,
16+
std::string infile);
17+
1518
} // namespace LFortran
1619

1720
#endif // LFORTRAN_PYTHON_AST_TO_ASR_H

0 commit comments

Comments
 (0)