From 5fe53355b5efaf3246c1f6e5e40c2f911957a8ef Mon Sep 17 00:00:00 2001 From: bog Date: Wed, 20 Sep 2023 21:21:51 +0200 Subject: [PATCH] ADD: native macros. --- libstd/commons.hpp | 2 ++ libstd/fun.cpp | 20 ++++++++++++++++++++ libstd/fun.hpp | 1 + libstd/lib.cpp | 4 ++++ libstd/macro.cpp | 25 +++++++++++++++++++++++++ libstd/macro.hpp | 12 ++++++++++++ meson.build | 3 +++ src/Compiler.cpp | 26 +++++++++++++++++++++----- src/Compiler.hpp | 13 ++++++++++--- src/Module.cpp | 7 +++++++ src/Module.hpp | 1 + src/NativeMacro.cpp | 23 +++++++++++++++++++++++ src/NativeMacro.hpp | 30 ++++++++++++++++++++++++++++++ src/main.cpp | 25 ++++++++++++++++++++++++- 14 files changed, 183 insertions(+), 9 deletions(-) create mode 100644 libstd/macro.cpp create mode 100644 libstd/macro.hpp create mode 100644 src/NativeMacro.cpp create mode 100644 src/NativeMacro.hpp diff --git a/libstd/commons.hpp b/libstd/commons.hpp index 2b48253..6664b2a 100644 --- a/libstd/commons.hpp +++ b/libstd/commons.hpp @@ -9,4 +9,6 @@ using namespace fk; #define STDARGS std::vector> #define STDRET std::shared_ptr +FK_ERROR(assert_error); + #endif diff --git a/libstd/fun.cpp b/libstd/fun.cpp index c6473e8..cf5e135 100644 --- a/libstd/fun.cpp +++ b/libstd/fun.cpp @@ -2,6 +2,26 @@ namespace fkstd { + STDRET assert_eq(STDARGS args) + { + auto oracle = args[0]; + auto expr = args[1]; + + if (!oracle->equals(*expr)) + { + std::stringstream ss; + ss << "assertion failed: expected '" + << oracle->string() + << "', got '" + << expr->string() + << "'"; + + oracle->loc().error(LOG_ERROR, ss.str()); + } + + return std::make_shared(TYPE_BOOL, true, oracle->loc()); + } + STDRET println(STDARGS args) { std::string sep; diff --git a/libstd/fun.hpp b/libstd/fun.hpp index fc00f91..dbd9846 100644 --- a/libstd/fun.hpp +++ b/libstd/fun.hpp @@ -4,6 +4,7 @@ namespace fkstd { + STDRET assert_eq(STDARGS args); STDRET println(STDARGS args); } diff --git a/libstd/lib.cpp b/libstd/lib.cpp index 36b79d5..1290d99 100644 --- a/libstd/lib.cpp +++ b/libstd/lib.cpp @@ -1,7 +1,11 @@ #include "commons.hpp" #include "fun.hpp" +#include "macro.hpp" extern "C" void lib(Module& mod) { + mod.register_function("assert=", fkstd::assert_eq); mod.register_function("println", fkstd::println); + + mod.register_macro("assert-static-fail", fkstd::assert_static_fail); } diff --git a/libstd/macro.cpp b/libstd/macro.cpp new file mode 100644 index 0000000..4e541c3 --- /dev/null +++ b/libstd/macro.cpp @@ -0,0 +1,25 @@ +#include "macro.hpp" + +namespace fkstd +{ + void assert_static_fail(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program) + { + try + { + compiler.compile_prog(node->child(1), program); + } + catch(std::exception const&) + { + program->load_const(std::make_shared(TYPE_BOOL, + true, + node->loc())); + return; + } + + std::stringstream ss; + ss << "assertion failed"; + node->loc().error(LOG_ERROR, ss.str()); + } +} diff --git a/libstd/macro.hpp b/libstd/macro.hpp new file mode 100644 index 0000000..880e304 --- /dev/null +++ b/libstd/macro.hpp @@ -0,0 +1,12 @@ +#ifndef fkstd_MACRO_HPP +#define fkstd_MACRO_HPP +#include "commons.hpp" + +namespace fkstd +{ + void assert_static_fail(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program); +} + +#endif diff --git a/meson.build b/meson.build index 4d2e546..d91ea7c 100644 --- a/meson.build +++ b/meson.build @@ -29,6 +29,7 @@ fakir_cpp = [ 'src/Parser.cpp', 'src/Constant.cpp', 'src/NativeFunction.cpp', + 'src/NativeMacro.cpp', 'src/SymTable.cpp', 'src/SymEntry.cpp', @@ -52,6 +53,7 @@ fakir_hpp = [ 'src/Program.hpp', 'src/Module.hpp', 'src/NativeFunction.hpp', + 'src/NativeMacro.hpp', 'src/opcodes.hpp', 'src/commons.hpp', 'src/types.hpp', @@ -74,6 +76,7 @@ shared_library('fakir-std', sources: [ 'libstd/lib.cpp', 'libstd/fun.cpp', + 'libstd/macro.cpp', ], dependencies: [ fakir_dep diff --git a/src/Compiler.cpp b/src/Compiler.cpp index 38ff21f..8af5c0f 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -11,6 +11,12 @@ namespace fk { } + void Compiler::add_macro(std::string const& name, + std::shared_ptr macro) + { + m_macros[name] = macro; + } + std::shared_ptr Compiler::compile(std::shared_ptr node) { auto prog = std::make_shared(); @@ -33,12 +39,22 @@ namespace fk case NODE_CALL: { std::string ident = node->child(0)->repr(); - for (size_t i=0; isize(); i++) - { - compile_prog(node->child(i), prog); - } - prog->add(OP_CALL_NATIVE, node->size() - 1); + if (auto itr=m_macros.find(ident); + itr != std::end(m_macros)) + { + auto macro = itr->second; + macro->call(*this, node, prog); + } + else + { + for (size_t i=0; isize(); i++) + { + compile_prog(node->child(i), prog); + } + + prog->add(OP_CALL_NATIVE, node->size() - 1); + } } break; case NODE_IDENT: { diff --git a/src/Compiler.hpp b/src/Compiler.hpp index 55546e9..2fb6c8e 100644 --- a/src/Compiler.hpp +++ b/src/Compiler.hpp @@ -5,6 +5,7 @@ #include "Program.hpp" #include "Node.hpp" #include "SymTable.hpp" +#include "NativeMacro.hpp" namespace fk { @@ -16,13 +17,19 @@ namespace fk explicit Compiler(std::shared_ptr sym); virtual ~Compiler(); - std::shared_ptr compile(std::shared_ptr node); + void add_macro(std::string const& name, + std::shared_ptr macro); - private: - std::shared_ptr m_sym; + std::shared_ptr compile(std::shared_ptr node); void compile_prog(std::shared_ptr node, std::shared_ptr prog); + + private: + std::shared_ptr m_sym; + std::unordered_map> m_macros; + }; } diff --git a/src/Module.cpp b/src/Module.cpp index aebb15f..9666d03 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -2,6 +2,7 @@ #include "conf.hpp" #include "Module.hpp" #include "Loc.hpp" +#include "NativeMacro.hpp" namespace fk { @@ -49,6 +50,12 @@ namespace fk m_sym->declare_global(name, addr, Loc {"extern"}); } + void Module::register_macro(std::string const& name, macro_t macro) + { + auto m = std::make_shared(macro); + m_compiler->add_macro(name, m); + } + std::string Module::load_sources() { std::ifstream file { m_source_path }; diff --git a/src/Module.hpp b/src/Module.hpp index a8a089f..13bf919 100644 --- a/src/Module.hpp +++ b/src/Module.hpp @@ -24,6 +24,7 @@ namespace fk void import_library(std::filesystem::path lib_path); void register_function(std::string const& name, native_t native); + void register_macro(std::string const& name, macro_t macro); private: std::filesystem::path m_source_path; diff --git a/src/NativeMacro.cpp b/src/NativeMacro.cpp new file mode 100644 index 0000000..4c16092 --- /dev/null +++ b/src/NativeMacro.cpp @@ -0,0 +1,23 @@ +#include "NativeMacro.hpp" +#include "Compiler.hpp" +#include "Program.hpp" +#include "Node.hpp" + +namespace fk +{ + /*explicit*/ NativeMacro::NativeMacro(macro_t macro) + : m_macro { macro } + { + } + + /*virtual*/ NativeMacro::~NativeMacro() + { + } + + void NativeMacro::call(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program) + { + m_macro(compiler, node, program); + } +} diff --git a/src/NativeMacro.hpp b/src/NativeMacro.hpp new file mode 100644 index 0000000..2c3014e --- /dev/null +++ b/src/NativeMacro.hpp @@ -0,0 +1,30 @@ +#ifndef fk_NATIVEMACRO_HPP +#define fk_NATIVEMACRO_HPP + +#include "commons.hpp" + +namespace fk +{ + class Compiler; + class Program; + class Node; + + using macro_t = std::function, + std::shared_ptr)>; + + class NativeMacro + { + public: + explicit NativeMacro(macro_t macro); + virtual ~NativeMacro(); + + void call(Compiler& compiler, + std::shared_ptr node, + std::shared_ptr program); + private: + macro_t m_macro; + }; +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index 7f6ad34..36e5adc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,10 +5,13 @@ int main(int argc, char** argv) { + bool debug_mode = false; + while (true) { static struct option options[] = { {"help", no_argument, 0, 'h'}, + {"debug", no_argument, 0, 'd'}, {0, 0, 0, 0} }; @@ -34,6 +37,10 @@ int main(int argc, char** argv) return 0; } break; + case 'd': { + debug_mode = true; + } break; + default: break; } } @@ -49,7 +56,23 @@ int main(int argc, char** argv) if (sources.size()) { fk::Module mod {sources[0]}; - mod.build(); + + if (debug_mode) + { + mod.build(); + } + else + { + try + { + mod.build(); + } + catch(std::exception const& err) + { + std::cerr << err.what() << std::endl; + return -1; + } + } } return 0;