ADD: native macros and assert-fail macro.

main
bog 2023-09-18 19:08:32 +02:00
parent 55c094e4ec
commit ee1b52cae1
13 changed files with 186 additions and 23 deletions

22
libstd/macro.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "macro.hpp"
std::shared_ptr<Constant> 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<Constant>(TYPE_NIL, node.loc(), 0);
}

11
libstd/macro.hpp Normal file
View File

@ -0,0 +1,11 @@
#ifndef MACRO_HPP
#define MACRO_HPP
#include "common.hpp"
std::shared_ptr<Constant> assert_fail(Node const& node,
Compiler& compiler,
Program& program,
SymTable& sym);
#endif

View File

@ -1,5 +1,7 @@
#include "common.hpp" #include "common.hpp"
#include "fun.hpp" #include "fun.hpp"
#include "macro.hpp"
#include "../src/types.hpp"
extern "C" void lib(Zarn& zarn) extern "C" void lib(Zarn& zarn)
{ {
@ -16,4 +18,6 @@ extern "C" void lib(Zarn& zarn)
->param_any() ->param_any()
->ret(TYPE_NIL), ->ret(TYPE_NIL),
assert_eq); assert_eq);
zarn.register_macro("assert-fail", assert_fail);
} }

View File

@ -37,6 +37,7 @@ zarn_lib = shared_library('zarn',
'src/SymTable.cpp', 'src/SymTable.cpp',
'src/NativeFunction.cpp', 'src/NativeFunction.cpp',
'src/Prototype.cpp', 'src/Prototype.cpp',
'src/NativeMacro.cpp',
'src/Zarn.cpp', 'src/Zarn.cpp',
], ],
install: true) install: true)
@ -49,6 +50,7 @@ shared_library('zarn-std',
sources: [ sources: [
'libstd/std.cpp', 'libstd/std.cpp',
'libstd/fun.cpp', 'libstd/fun.cpp',
'libstd/macro.cpp',
], ],
dependencies: [ dependencies: [
zarn_dep zarn_dep

View File

@ -1,6 +1,7 @@
#include "Compiler.hpp" #include "Compiler.hpp"
#include "src/Node.hpp" #include "Node.hpp"
#include "src/Program.hpp" #include "Program.hpp"
#include "NativeMacro.hpp"
namespace zn namespace zn
{ {
@ -14,6 +15,11 @@ namespace zn
{ {
} }
void Compiler::add_macro(std::shared_ptr<NativeMacro> macro)
{
m_macros.push_back(macro);
}
void Compiler::compile(Node const& node, Program& program) void Compiler::compile(Node const& node, Program& program)
{ {
switch (node.type()) switch (node.type())
@ -31,12 +37,47 @@ namespace zn
// FUNCTION STUFF // FUNCTION STUFF
// ============== // ==============
case NODE_CALL: { case NODE_CALL: {
for (size_t i=0; i<node.size(); i++) std::string ident = node.child_at(0)->repr();
{ auto sym = m_sym.find(ident);
compile(*node.child_at(i), program);
}
program.append(OPCODE_CALL_NATIVE, node.size() - 1); if (sym)
{
for (size_t i=0; i<node.size(); i++)
{
compile(*node.child_at(i), program);
}
program.append(OPCODE_CALL_NATIVE, node.size() - 1);
}
else
{
bool found_macro = false;
for (auto macro: m_macros)
{
if (macro->name() == 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<compile_error>(LOG_ERROR,
node.loc(),
ss.str());
}
}
} break; } break;
// VALUES // VALUES
@ -44,7 +85,18 @@ namespace zn
case NODE_IDENT: { case NODE_IDENT: {
std::string ident = node.repr(); std::string ident = node.repr();
auto sym = m_sym.find(ident); auto sym = m_sym.find(ident);
assert(sym);
if (!sym)
{
std::stringstream ss;
ss << "cannot use undefined variable '"
<< ident
<< "'";
m_logger.log<compile_error>(LOG_ERROR,
node.loc(),
ss.str());
}
if (sym->prototype) if (sym->prototype)
{ {

View File

@ -11,17 +11,21 @@ namespace zn
{ {
ZN_ERROR(compile_error); ZN_ERROR(compile_error);
class NativeMacro;
class Compiler class Compiler
{ {
public: public:
explicit Compiler(Logger& logger, SymTable& sym); explicit Compiler(Logger& logger, SymTable& sym);
virtual ~Compiler(); virtual ~Compiler();
void add_macro(std::shared_ptr<NativeMacro> macro);
void compile(Node const& node, Program& program); void compile(Node const& node, Program& program);
private: private:
Logger& m_logger; Logger& m_logger;
SymTable& m_sym; SymTable& m_sym;
std::vector<std::shared_ptr<NativeMacro>> m_macros;
}; };
} }

View File

@ -51,8 +51,7 @@ namespace zn
StaticPass static_pass { m_logger, m_sym }; StaticPass static_pass { m_logger, m_sym };
static_pass.execute(*ast); static_pass.execute(*ast);
Compiler compiler { m_logger, m_sym }; m_compiler.compile(*ast, m_program);
compiler.compile(*ast, m_program);
m_vm.execute(m_program); m_vm.execute(m_program);
} }

View File

@ -27,7 +27,8 @@ namespace zn
Program m_program; Program m_program;
VM m_vm { m_program }; VM m_vm { m_program };
SymTable m_sym; 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};
}; };
} }

24
src/NativeMacro.cpp Normal file
View File

@ -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<Constant>
NativeMacro::execute(Node const& node,
Compiler& compiler,
Program& program,
SymTable& sym)
{
return m_macro(node, compiler, program, sym);
}
}

38
src/NativeMacro.hpp Normal file
View File

@ -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<std::shared_ptr<Constant>
(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<Constant>
execute(Node const& node,
Compiler& compiler,
Program& program,
SymTable& sym);
private:
std::string m_name;
native_macro_t m_macro;
};
}
#endif

View File

@ -31,11 +31,7 @@ namespace zn
if (sym == std::nullopt) if (sym == std::nullopt)
{ {
m_logger.log<static_error>(LOG_ERROR, return TypeSlot {TYPE_NIL, TAG_ANY};
node.loc(),
"cannot call unknown function '"
+ ident
+ "'");
} }
auto proto = sym->prototype; auto proto = sym->prototype;

View File

@ -4,8 +4,9 @@
namespace zn namespace zn
{ {
/*explicit*/ Zarn::Zarn(SymTable& sym, VM& vm) /*explicit*/ Zarn::Zarn(Compiler& compiler, SymTable& sym, VM& vm)
: m_sym { sym } : m_compiler { compiler }
, m_sym { sym }
, m_vm { vm } , m_vm { vm }
{ {
} }
@ -27,12 +28,16 @@ namespace zn
auto func = std::make_shared<NativeFunction>(prototype, body); auto func = std::make_shared<NativeFunction>(prototype, body);
int addr = m_vm.store_global(func); int addr = m_vm.store_global(func);
m_sym.declare_function(name, addr, prototype); m_sym.declare_function(name, addr, prototype);
// auto ref = std::make_shared<Constant>(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<NativeMacro>(name, macro);
m_compiler.add_macro(m);
}
void Zarn::load_std_library() void Zarn::load_std_library()
{ {
load_library(ZN_LIBDIR / "libzarn-std.so"); load_library(ZN_LIBDIR / "libzarn-std.so");

View File

@ -4,22 +4,27 @@
#include "common.hpp" #include "common.hpp"
#include "SymTable.hpp" #include "SymTable.hpp"
#include "VM.hpp" #include "VM.hpp"
#include "src/NativeMacro.hpp"
namespace zn namespace zn
{ {
class Zarn class Zarn
{ {
public: public:
explicit Zarn(SymTable& sym, VM& vm); explicit Zarn(Compiler& compiler, SymTable& sym, VM& vm);
virtual ~Zarn(); virtual ~Zarn();
void register_function(std::string const& name, void register_function(std::string const& name,
std::shared_ptr<Prototype> prototype, std::shared_ptr<Prototype> prototype,
native_fn_t body); native_fn_t body);
void register_macro(std::string const& name,
native_macro_t macro);
void load_std_library(); void load_std_library();
void load_library(std::filesystem::path lib_path); void load_library(std::filesystem::path lib_path);
private: private:
Compiler& m_compiler;
SymTable& m_sym; SymTable& m_sym;
VM& m_vm; VM& m_vm;
std::vector<void*> m_handlers; std::vector<void*> m_handlers;