diff --git a/compiler/src/ast/codefiles.cpp b/compiler/src/ast/codefiles.cpp index 18b59e2c..48bf6d44 100644 --- a/compiler/src/ast/codefiles.cpp +++ b/compiler/src/ast/codefiles.cpp @@ -92,6 +92,7 @@ file_info *codefiles::initialize_parsing_or_null(const std::string &filename) { std::error_code err{}; std::filesystem::path f{filename}; auto path = std::filesystem::absolute(f, err); + path = scratch_file_path(path.string()); std::string str_path = path.string(); if (err) { print_file_not_found_error(str_path); @@ -184,6 +185,7 @@ codefiles::import_to_optional_file_path(import_stmt *st) { } p += ".yaka"; /* add .yaka file extension */ p = std::filesystem::absolute(p, err); + p = scratch_file_path(p.string()); // check for scratch files if (err) { print_file_not_found_error(p.string()); return {}; @@ -210,9 +212,31 @@ file_data *codefiles::parse_or_null(std::filesystem::path &file_name) { } std::string data((std::istreambuf_iterator(script_file)), std::istreambuf_iterator()); + script_file.close(); // close the file std::string fname = file_name.string(); return parse_or_null(data, fname); } +std::filesystem::path codefiles::scratch_file_path(const std::string &filename) const { + if (!this->use_scratch_files_) { + return std::filesystem::path{filename}; + } + std::filesystem::path f{filename}; + auto path = f.parent_path(); + auto name = f.stem(); + // Already a scratch file + if (name.string().find("_.") == 0) { + return std::filesystem::path{filename}; + } + auto ext = f.extension(); + auto scratch_path = path / ("_." + name.string() + ext.string()); + std::error_code err{}; + if (std::filesystem::exists(scratch_path, err)) { + if (!err) { + return scratch_path; + } + } + return std::filesystem::path{filename}; +} file_data *codefiles::parse_or_null(const std::string &data, const std::string &file_name) { auto *t = new tokenizer{file_name, data, yaksha_macros_.get_yk_token_pool()}; diff --git a/compiler/src/ast/codefiles.h b/compiler/src/ast/codefiles.h index 36739f2e..7b5417dd 100644 --- a/compiler/src/ast/codefiles.h +++ b/compiler/src/ast/codefiles.h @@ -81,6 +81,7 @@ namespace yaksha { entry_struct_func_compiler *esc_; directives directives_{}; std::filesystem::path libs_path_{}; + bool use_scratch_files_{false}; private: file_data *parse_or_null(std::filesystem::path &file_name); @@ -98,6 +99,7 @@ namespace yaksha { std::unordered_map import_to_path_cache_{}; errors::error_printer *ep_{nullptr}; + std::filesystem::path scratch_file_path(const std::string &filename) const; }; }// namespace yaksha #endif diff --git a/compiler/src/comp_main.cpp b/compiler/src/comp_main.cpp index 42c96d7c..5c045275 100644 --- a/compiler/src/comp_main.cpp +++ b/compiler/src/comp_main.cpp @@ -53,7 +53,11 @@ int main(int argc, char *argv[]) { auto no_codegen = argparser::OP_BOOL( 'd', "--disable-codegen", "Do not output generated code, instead just print errors as JSON."); - args.optional_ = {&help, &no_main, &no_codegen}; + auto use_scratch_files = + argparser::OP_BOOL('e', "--use-scratch-files", + "Use scratch files such as '_.main.yaka' if present " + "in the same directory instead of 'main.yaka'."); + args.optional_ = {&help, &no_main, &no_codegen, &use_scratch_files}; auto code = argparser::PO("mainfile.yaka", "Yaksha code file."); auto lib = argparser::PO_OPT("[LIBS_PARENT_PATH]", "Path to the parent directory of the libraries"); @@ -72,6 +76,7 @@ int main(int argc, char *argv[]) { multifile_compiler mc{}; try { mc.main_required_ = !no_main.is_set_; + mc.use_scratch_files_ = use_scratch_files.is_set_; if (no_codegen.is_set_) { mc.error_printer_.json_output_ = true; } codegen_c cg{}; do_nothing_codegen dn_cg{}; diff --git a/compiler/src/compiler/multifile_compiler.cpp b/compiler/src/compiler/multifile_compiler.cpp index 25cc65f8..04bc9729 100644 --- a/compiler/src/compiler/multifile_compiler.cpp +++ b/compiler/src/compiler/multifile_compiler.cpp @@ -40,7 +40,6 @@ #include "multifile_compiler.h" #include "ast/codefiles.h" #include "ast/parser.h" -//#include "compiler/compiler.h" #include "compiler/type_checker.h" #include "tokenizer/block_analyzer.h" #include "usage_analyser.h" @@ -69,6 +68,7 @@ comp_result multifile_compiler::compile(const std::string &code, bool use_code, LOG_COMP("compile:" << main_file); std::filesystem::path library_parent{libs_path}; cf_ = new codefiles{library_parent, &error_printer_}; + cf_->use_scratch_files_ = use_scratch_files_; // Step 0) First of all, we initialize parsing // In this step, we initialize all files we know of at this point file_info *main_file_info; diff --git a/compiler/src/compiler/multifile_compiler.h b/compiler/src/compiler/multifile_compiler.h index 7956288d..0eae6bb6 100644 --- a/compiler/src/compiler/multifile_compiler.h +++ b/compiler/src/compiler/multifile_compiler.h @@ -65,6 +65,7 @@ namespace yaksha { bool main_required_ = true; bool check_types_ = true; bool usage_analysis_ = true; + bool use_scratch_files_ = false; errors::error_printer error_printer_{}; private: