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 "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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
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;
|
||||||
|
|
17
src/Zarn.cpp
17
src/Zarn.cpp
|
@ -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");
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Reference in New Issue