From ee1b52cae10d21b2aedfd4351ac8413254fb9cf4 Mon Sep 17 00:00:00 2001 From: bog Date: Mon, 18 Sep 2023 19:08:32 +0200 Subject: [PATCH] ADD: native macros and assert-fail macro. --- libstd/macro.cpp | 22 +++++++++++++++ libstd/macro.hpp | 11 ++++++++ libstd/std.cpp | 4 +++ meson.build | 2 ++ src/Compiler.cpp | 68 +++++++++++++++++++++++++++++++++++++++------ src/Compiler.hpp | 4 +++ src/Module.cpp | 3 +- src/Module.hpp | 3 +- src/NativeMacro.cpp | 24 ++++++++++++++++ src/NativeMacro.hpp | 38 +++++++++++++++++++++++++ src/StaticPass.cpp | 6 +--- src/Zarn.cpp | 17 ++++++++---- src/Zarn.hpp | 7 ++++- 13 files changed, 186 insertions(+), 23 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/macro.cpp b/libstd/macro.cpp new file mode 100644 index 0000000..41a1188 --- /dev/null +++ b/libstd/macro.cpp @@ -0,0 +1,22 @@ +#include "macro.hpp" + +std::shared_ptr assert_fail(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym) +{ + try + { + compiler.compile(*node.child_at(1), program); + Loc loc = node.loc(); + + std::cerr << loc.file_path().string() << ":" << loc.line(); + std::cerr << " ASSERTION FAILED" << std::endl; + exit(-1); + } + catch (std::exception const&) + { + } + + return std::make_shared(TYPE_NIL, node.loc(), 0); +} diff --git a/libstd/macro.hpp b/libstd/macro.hpp new file mode 100644 index 0000000..c342446 --- /dev/null +++ b/libstd/macro.hpp @@ -0,0 +1,11 @@ +#ifndef MACRO_HPP +#define MACRO_HPP + +#include "common.hpp" + +std::shared_ptr assert_fail(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym); + +#endif diff --git a/libstd/std.cpp b/libstd/std.cpp index b6297ba..ddbd97d 100644 --- a/libstd/std.cpp +++ b/libstd/std.cpp @@ -1,5 +1,7 @@ #include "common.hpp" #include "fun.hpp" +#include "macro.hpp" +#include "../src/types.hpp" extern "C" void lib(Zarn& zarn) { @@ -16,4 +18,6 @@ extern "C" void lib(Zarn& zarn) ->param_any() ->ret(TYPE_NIL), assert_eq); + + zarn.register_macro("assert-fail", assert_fail); } diff --git a/meson.build b/meson.build index cf9c799..a4a2f4d 100644 --- a/meson.build +++ b/meson.build @@ -37,6 +37,7 @@ zarn_lib = shared_library('zarn', 'src/SymTable.cpp', 'src/NativeFunction.cpp', 'src/Prototype.cpp', + 'src/NativeMacro.cpp', 'src/Zarn.cpp', ], install: true) @@ -49,6 +50,7 @@ shared_library('zarn-std', sources: [ 'libstd/std.cpp', 'libstd/fun.cpp', + 'libstd/macro.cpp', ], dependencies: [ zarn_dep diff --git a/src/Compiler.cpp b/src/Compiler.cpp index 0eca30f..1458e2b 100644 --- a/src/Compiler.cpp +++ b/src/Compiler.cpp @@ -1,6 +1,7 @@ #include "Compiler.hpp" -#include "src/Node.hpp" -#include "src/Program.hpp" +#include "Node.hpp" +#include "Program.hpp" +#include "NativeMacro.hpp" namespace zn { @@ -14,6 +15,11 @@ namespace zn { } + void Compiler::add_macro(std::shared_ptr macro) + { + m_macros.push_back(macro); + } + void Compiler::compile(Node const& node, Program& program) { switch (node.type()) @@ -31,12 +37,47 @@ namespace zn // FUNCTION STUFF // ============== case NODE_CALL: { - for (size_t i=0; irepr(); + auto sym = m_sym.find(ident); - program.append(OPCODE_CALL_NATIVE, node.size() - 1); + if (sym) + { + for (size_t i=0; iname() == ident) + { + auto res = macro->execute(node, *this, + program, m_sym); + size_t addr = program.add_constant(res); + program.append(OPCODE_LOAD_CONST, addr); + found_macro = true; + break; + } + } + + if (!found_macro) + { + std::stringstream ss; + ss << "cannot call undefined function '" + << ident + << "'"; + + m_logger.log(LOG_ERROR, + node.loc(), + ss.str()); + } + } } break; // VALUES @@ -44,7 +85,18 @@ namespace zn case NODE_IDENT: { std::string ident = node.repr(); auto sym = m_sym.find(ident); - assert(sym); + + if (!sym) + { + std::stringstream ss; + ss << "cannot use undefined variable '" + << ident + << "'"; + + m_logger.log(LOG_ERROR, + node.loc(), + ss.str()); + } if (sym->prototype) { diff --git a/src/Compiler.hpp b/src/Compiler.hpp index c6a1d3a..ec91e85 100644 --- a/src/Compiler.hpp +++ b/src/Compiler.hpp @@ -11,17 +11,21 @@ namespace zn { ZN_ERROR(compile_error); + class NativeMacro; + class Compiler { public: explicit Compiler(Logger& logger, SymTable& sym); virtual ~Compiler(); + void add_macro(std::shared_ptr macro); void compile(Node const& node, Program& program); private: Logger& m_logger; SymTable& m_sym; + std::vector> m_macros; }; } diff --git a/src/Module.cpp b/src/Module.cpp index 1899164..f722ae0 100644 --- a/src/Module.cpp +++ b/src/Module.cpp @@ -51,8 +51,7 @@ namespace zn StaticPass static_pass { m_logger, m_sym }; static_pass.execute(*ast); - Compiler compiler { m_logger, m_sym }; - compiler.compile(*ast, m_program); + m_compiler.compile(*ast, m_program); m_vm.execute(m_program); } diff --git a/src/Module.hpp b/src/Module.hpp index 33ab63a..8a51b08 100644 --- a/src/Module.hpp +++ b/src/Module.hpp @@ -27,7 +27,8 @@ namespace zn Program m_program; VM m_vm { m_program }; SymTable m_sym; - Zarn m_zarn {m_sym, m_vm}; + Compiler m_compiler {m_logger, m_sym}; + Zarn m_zarn {m_compiler, m_sym, m_vm}; }; } diff --git a/src/NativeMacro.cpp b/src/NativeMacro.cpp new file mode 100644 index 0000000..41d012c --- /dev/null +++ b/src/NativeMacro.cpp @@ -0,0 +1,24 @@ +#include "NativeMacro.hpp" + +namespace zn +{ + /*explicit*/ NativeMacro::NativeMacro(std::string const& name, + native_macro_t macro) + : m_name { name } + , m_macro { macro } + { + } + + /*virtual*/ NativeMacro::~NativeMacro() + { + } + + std::shared_ptr + NativeMacro::execute(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym) + { + return m_macro(node, compiler, program, sym); + } +} diff --git a/src/NativeMacro.hpp b/src/NativeMacro.hpp new file mode 100644 index 0000000..2f7c0f1 --- /dev/null +++ b/src/NativeMacro.hpp @@ -0,0 +1,38 @@ +#ifndef zn_NATIVEMACRO_HPP +#define zn_NATIVEMACRO_HPP + +#include "common.hpp" + +#include "Compiler.hpp" +#include "SymTable.hpp" +#include "Node.hpp" + +namespace zn +{ + using native_macro_t = std::function + (Node const&, + Compiler&, + Program&, + SymTable&)>; + + class NativeMacro + { + public: + explicit NativeMacro(std::string const& name, native_macro_t macro); + virtual ~NativeMacro(); + + std::string name() const { return m_name; } + + std::shared_ptr + execute(Node const& node, + Compiler& compiler, + Program& program, + SymTable& sym); + + private: + std::string m_name; + native_macro_t m_macro; + }; +} + +#endif diff --git a/src/StaticPass.cpp b/src/StaticPass.cpp index 8f713f8..93ca936 100644 --- a/src/StaticPass.cpp +++ b/src/StaticPass.cpp @@ -31,11 +31,7 @@ namespace zn if (sym == std::nullopt) { - m_logger.log(LOG_ERROR, - node.loc(), - "cannot call unknown function '" - + ident - + "'"); + return TypeSlot {TYPE_NIL, TAG_ANY}; } auto proto = sym->prototype; diff --git a/src/Zarn.cpp b/src/Zarn.cpp index 0e50f71..592b8dd 100644 --- a/src/Zarn.cpp +++ b/src/Zarn.cpp @@ -4,8 +4,9 @@ namespace zn { - /*explicit*/ Zarn::Zarn(SymTable& sym, VM& vm) - : m_sym { sym } + /*explicit*/ Zarn::Zarn(Compiler& compiler, SymTable& sym, VM& vm) + : m_compiler { compiler } + , m_sym { sym } , m_vm { vm } { } @@ -27,12 +28,16 @@ namespace zn auto func = std::make_shared(prototype, body); int addr = m_vm.store_global(func); m_sym.declare_function(name, addr, prototype); - - // auto ref = std::make_shared(TYPE_REF, addr); - // m_vm.store_local(0, ref); - // m_sym.declare_function(name, 0, prototype); } + void Zarn::register_macro(std::string const& name, + native_macro_t macro) + { + auto m = std::make_shared(name, macro); + m_compiler.add_macro(m); + } + + void Zarn::load_std_library() { load_library(ZN_LIBDIR / "libzarn-std.so"); diff --git a/src/Zarn.hpp b/src/Zarn.hpp index ff7a8e0..51465fb 100644 --- a/src/Zarn.hpp +++ b/src/Zarn.hpp @@ -4,22 +4,27 @@ #include "common.hpp" #include "SymTable.hpp" #include "VM.hpp" +#include "src/NativeMacro.hpp" namespace zn { class Zarn { public: - explicit Zarn(SymTable& sym, VM& vm); + explicit Zarn(Compiler& compiler, SymTable& sym, VM& vm); virtual ~Zarn(); void register_function(std::string const& name, std::shared_ptr prototype, native_fn_t body); + void register_macro(std::string const& name, + native_macro_t macro); + void load_std_library(); void load_library(std::filesystem::path lib_path); private: + Compiler& m_compiler; SymTable& m_sym; VM& m_vm; std::vector m_handlers;