ADD: native macros and assert-fail macro.
parent
55c094e4ec
commit
ee1b52cae1
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<NativeMacro> 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; i<node.size(); i++)
|
||||
{
|
||||
compile(*node.child_at(i), program);
|
||||
}
|
||||
std::string ident = node.child_at(0)->repr();
|
||||
auto sym = m_sym.find(ident);
|
||||
|
||||
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;
|
||||
|
||||
// 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<compile_error>(LOG_ERROR,
|
||||
node.loc(),
|
||||
ss.str());
|
||||
}
|
||||
|
||||
if (sym->prototype)
|
||||
{
|
||||
|
|
|
@ -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<NativeMacro> macro);
|
||||
void compile(Node const& node, Program& program);
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
SymTable& m_sym;
|
||||
std::vector<std::shared_ptr<NativeMacro>> m_macros;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -31,11 +31,7 @@ namespace zn
|
|||
|
||||
if (sym == std::nullopt)
|
||||
{
|
||||
m_logger.log<static_error>(LOG_ERROR,
|
||||
node.loc(),
|
||||
"cannot call unknown function '"
|
||||
+ ident
|
||||
+ "'");
|
||||
return TypeSlot {TYPE_NIL, TAG_ANY};
|
||||
}
|
||||
|
||||
auto proto = sym->prototype;
|
||||
|
|
17
src/Zarn.cpp
17
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<NativeFunction>(prototype, body);
|
||||
int addr = m_vm.store_global(func);
|
||||
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()
|
||||
{
|
||||
load_library(ZN_LIBDIR / "libzarn-std.so");
|
||||
|
|
|
@ -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> 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<void*> m_handlers;
|
||||
|
|
Reference in New Issue