From 1de0cbb6f60bc4bdb6022a205c5597ac3783ba28 Mon Sep 17 00:00:00 2001 From: water Date: Sun, 6 Sep 2020 17:42:20 -0400 Subject: [PATCH] enable macros --- goal_src/goal-lib.gc | 9 +++++ goalc/CMakeLists.txt | 1 + goalc/compiler/Compiler.cpp | 24 +++++++----- goalc/compiler/Compiler.h | 6 +++ goalc/compiler/Env.cpp | 4 ++ goalc/compiler/Env.h | 3 +- goalc/compiler/compilation/Atoms.cpp | 10 +++-- .../compiler/compilation/CompilerControl.cpp | 12 ++++++ goalc/compiler/compilation/Macro.cpp | 37 +++++++++++++++++++ goalc/goos/Interpreter.h | 19 +++++----- 10 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 goal_src/goal-lib.gc create mode 100644 goalc/compiler/compilation/Macro.cpp diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc new file mode 100644 index 000000000..af0e1fad0 --- /dev/null +++ b/goal_src/goal-lib.gc @@ -0,0 +1,9 @@ +;; compile, color, and save a file +(defmacro m (file) + `(asm-file ,file :color :write) + ) + +;; compile, color, load and save a file +(defmacro ml (file) + `(asm-file ,file :color :load :write) + ) \ No newline at end of file diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index c63f22b51..63cdb110e 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(compiler compiler/compilation/Atoms.cpp compiler/compilation/CompilerControl.cpp compiler/compilation/Block.cpp + compiler/compilation/Macro.cpp compiler/Util.cpp logger/Logger.cpp regalloc/IRegister.cpp diff --git a/goalc/compiler/Compiler.cpp b/goalc/compiler/Compiler.cpp index fe2106f43..d9d062e9b 100644 --- a/goalc/compiler/Compiler.cpp +++ b/goalc/compiler/Compiler.cpp @@ -14,10 +14,12 @@ Compiler::Compiler() { m_none = std::make_unique(m_ts.make_typespec("none")); // todo - compile library + Object library_code = m_goos.reader.read_from_file("goal_src/goal-lib.gc"); + compile_object_file("goal-lib", library_code, false); } void Compiler::execute_repl() { - m_listener.connect_to_target(); + m_listener.connect_to_target(); // todo, remove while (!m_want_exit) { try { // 1). get a line from the user (READ) @@ -33,17 +35,19 @@ void Compiler::execute_repl() { auto obj_file = compile_object_file("repl", code, m_listener.is_connected()); obj_file->debug_print_tl(); - // 3). color - color_object_file(obj_file); + if (!obj_file->is_empty()) { + // 3). color + color_object_file(obj_file); - // 4). codegen - auto data = codegen_object_file(obj_file); + // 4). codegen + auto data = codegen_object_file(obj_file); - // 4). send! - if (m_listener.is_connected()) { - m_listener.send_code(data); - if (!m_listener.most_recent_send_was_acked()) { - gLogger.log(MSG_ERR, "Runtime is not responding. Did it crash?\n"); + // 4). send! + if (m_listener.is_connected()) { + m_listener.send_code(data); + if (!m_listener.most_recent_send_was_acked()) { + gLogger.log(MSG_ERR, "Runtime is not responding. Did it crash?\n"); + } } } diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index dc5f67f24..16722ea81 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -27,6 +27,11 @@ class Compiler { private: void init_logger(); + bool try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest); + Val* compile_goos_macro(const goos::Object& o, + const goos::Object& macro_obj, + const goos::Object& rest, + Env* env); Val* compile_pair(const goos::Object& code, Env* env); Val* compile_integer(const goos::Object& code, Env* env); Val* compile_integer(s64 value, Env* env); @@ -55,6 +60,7 @@ class Compiler { Val* compile_exit(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_top_level(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_begin(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_seval(const goos::Object& form, const goos::Object& rest, Env* env); }; #endif // JAK_COMPILER_H diff --git a/goalc/compiler/Env.cpp b/goalc/compiler/Env.cpp index e6a7b500b..50bc15328 100644 --- a/goalc/compiler/Env.cpp +++ b/goalc/compiler/Env.cpp @@ -159,6 +159,10 @@ void FileEnv::debug_print_tl() { } } +bool FileEnv::is_empty() { + return m_functions.size() == 1 && m_functions.front().get() == m_top_level_func && + m_top_level_func->code().empty(); +} /////////////////// // FunctionEnv /////////////////// diff --git a/goalc/compiler/Env.h b/goalc/compiler/Env.h index 056c2aa3c..8a3c7baad 100644 --- a/goalc/compiler/Env.h +++ b/goalc/compiler/Env.h @@ -89,6 +89,7 @@ class FileEnv : public Env { const std::vector>& functions() { return m_functions; } // todo - is_empty + bool is_empty(); ~FileEnv() = default; protected: @@ -141,6 +142,7 @@ class FunctionEnv : public DeclareEnv { return (T*)m_vals.back().get(); } int segment = -1; + std::string method_of_type_name = "#f"; protected: std::string m_name; @@ -152,7 +154,6 @@ class FunctionEnv : public DeclareEnv { AllocationResult m_regalloc_result; bool m_is_asm_func = false; - std::string m_method_of_type_name = "#f"; bool m_aligned_stack_required = false; std::unordered_map m_params; diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index 00ff0aa74..7fd4039d5 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -26,7 +26,7 @@ static const std::unordered_map< // // // COMPILER CONTROL // {"gs", &Compiler::compile_gs}, - {":exit", &Compiler::compile_exit} + {":exit", &Compiler::compile_exit}, // {"asm-file", &Compiler::compile_asm_file}, // {"test", &Compiler::compile_test}, // {"in-package", &Compiler::compile_in_package}, @@ -34,7 +34,7 @@ static const std::unordered_map< // // CONDITIONAL COMPILATION // {"#cond", &Compiler::compile_gscond}, // {"defglobalconstant", &Compiler::compile_defglobalconstant}, - // {"seval", &Compiler::compile_seval}, + {"seval", &Compiler::compile_seval}, // // // CONTROL FLOW // {"cond", &Compiler::compile_cond}, @@ -159,7 +159,11 @@ Val* Compiler::compile_pair(const goos::Object& code, Env* env) { return ((*this).*(kv_gfs->second))(code, rest, env); } - // todo macro + goos::Object macro_obj; + if (try_getting_macro_from_goos(head, ¯o_obj)) { + return compile_goos_macro(code, macro_obj, rest, env); + } + // todo enum } diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index c666ac882..2d83f48ff 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -10,4 +10,16 @@ Val* Compiler::compile_exit(const goos::Object& form, const goos::Object& rest, } m_want_exit = true; return get_none(); +} + +Val* Compiler::compile_seval(const goos::Object& form, const goos::Object& rest, Env* env) { + (void)env; + try { + for_each_in_list(rest, [&](const goos::Object& o) { + m_goos.eval_with_rewind(o, m_goos.global_environment.as_env()); + }); + } catch (std::runtime_error& e) { + throw_compile_error(form, std::string("seval error: ") + e.what()); + } + return get_none(); } \ No newline at end of file diff --git a/goalc/compiler/compilation/Macro.cpp b/goalc/compiler/compilation/Macro.cpp new file mode 100644 index 000000000..275207c19 --- /dev/null +++ b/goalc/compiler/compilation/Macro.cpp @@ -0,0 +1,37 @@ +#include "goalc/compiler/Compiler.h" + +using namespace goos; + +bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest) { + Object macro_obj; + bool got_macro = false; + try { + macro_obj = m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env()); + if (macro_obj.is_macro()) { + got_macro = true; + } + } catch (std::runtime_error& e) { + got_macro = false; + } + + if (got_macro) { + *dest = macro_obj; + } + return got_macro; +} + +Val* Compiler::compile_goos_macro(const goos::Object& o, + const goos::Object& macro_obj, + const goos::Object& rest, + Env* env) { + auto macro = macro_obj.as_macro(); + Arguments args = m_goos.get_args(o, rest, macro->args); + auto mac_env_obj = EnvironmentObject::make_new(); + auto mac_env = mac_env_obj.as_env(); + m_goos.set_args_in_env(o, args, macro->args, mac_env); + m_goos.goal_to_goos.enclosing_method_type = + get_parent_env_of_type(env)->method_of_type_name; + auto goos_result = m_goos.eval_list_return_last(macro->body, macro->body, mac_env); + m_goos.goal_to_goos.reset(); + return compile_error_guard(goos_result, env); +} \ No newline at end of file diff --git a/goalc/goos/Interpreter.h b/goalc/goos/Interpreter.h index b19903e68..d58f46670 100644 --- a/goalc/goos/Interpreter.h +++ b/goalc/goos/Interpreter.h @@ -23,6 +23,15 @@ class Interpreter { Object eval(Object obj, const std::shared_ptr& env); Object intern(const std::string& name); void disable_printfs(); + Object eval_symbol(const Object& sym, const std::shared_ptr& env); + Arguments get_args(const Object& form, const Object& rest, const ArgumentSpec& spec); + void set_args_in_env(const Object& form, + const Arguments& args, + const ArgumentSpec& arg_spec, + const std::shared_ptr& env); + Object eval_list_return_last(const Object& form, + Object rest, + const std::shared_ptr& env); Reader reader; Object global_environment; @@ -47,14 +56,9 @@ class Interpreter { const std::unordered_map>>& named); Object eval_pair(const Object& o, const std::shared_ptr& env); - Object eval_symbol(const Object& sym, const std::shared_ptr& env); - Arguments get_args(const Object& form, const Object& rest, const ArgumentSpec& spec); void eval_args(Arguments* args, const std::shared_ptr& env); ArgumentSpec parse_arg_spec(const Object& form, Object& rest); - Object eval_list_return_last(const Object& form, - Object rest, - const std::shared_ptr& env); Object quasiquote_helper(const Object& form, const std::shared_ptr& env); IntType number_to_integer(const Object& obj); @@ -206,11 +210,6 @@ class Interpreter { const Object& rest, const std::shared_ptr& env); - void set_args_in_env(const Object& form, - const Arguments& args, - const ArgumentSpec& arg_spec, - const std::shared_ptr& env); - bool want_exit = false; bool disable_printing = false;