ADD: native macros.

main
bog 2023-09-20 21:21:51 +02:00
parent bcf12d19f7
commit 5fe53355b5
14 changed files with 183 additions and 9 deletions

View File

@ -9,4 +9,6 @@ using namespace fk;
#define STDARGS std::vector<std::shared_ptr<Constant>> #define STDARGS std::vector<std::shared_ptr<Constant>>
#define STDRET std::shared_ptr<Constant> #define STDRET std::shared_ptr<Constant>
FK_ERROR(assert_error);
#endif #endif

View File

@ -2,6 +2,26 @@
namespace fkstd 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<assert_error>(LOG_ERROR, ss.str());
}
return std::make_shared<Constant>(TYPE_BOOL, true, oracle->loc());
}
STDRET println(STDARGS args) STDRET println(STDARGS args)
{ {
std::string sep; std::string sep;

View File

@ -4,6 +4,7 @@
namespace fkstd namespace fkstd
{ {
STDRET assert_eq(STDARGS args);
STDRET println(STDARGS args); STDRET println(STDARGS args);
} }

View File

@ -1,7 +1,11 @@
#include "commons.hpp" #include "commons.hpp"
#include "fun.hpp" #include "fun.hpp"
#include "macro.hpp"
extern "C" void lib(Module& mod) extern "C" void lib(Module& mod)
{ {
mod.register_function("assert=", fkstd::assert_eq);
mod.register_function("println", fkstd::println); mod.register_function("println", fkstd::println);
mod.register_macro("assert-static-fail", fkstd::assert_static_fail);
} }

25
libstd/macro.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "macro.hpp"
namespace fkstd
{
void assert_static_fail(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program)
{
try
{
compiler.compile_prog(node->child(1), program);
}
catch(std::exception const&)
{
program->load_const(std::make_shared<Constant>(TYPE_BOOL,
true,
node->loc()));
return;
}
std::stringstream ss;
ss << "assertion failed";
node->loc().error<assert_error>(LOG_ERROR, ss.str());
}
}

12
libstd/macro.hpp Normal file
View File

@ -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> node,
std::shared_ptr<Program> program);
}
#endif

View File

@ -29,6 +29,7 @@ fakir_cpp = [
'src/Parser.cpp', 'src/Parser.cpp',
'src/Constant.cpp', 'src/Constant.cpp',
'src/NativeFunction.cpp', 'src/NativeFunction.cpp',
'src/NativeMacro.cpp',
'src/SymTable.cpp', 'src/SymTable.cpp',
'src/SymEntry.cpp', 'src/SymEntry.cpp',
@ -52,6 +53,7 @@ fakir_hpp = [
'src/Program.hpp', 'src/Program.hpp',
'src/Module.hpp', 'src/Module.hpp',
'src/NativeFunction.hpp', 'src/NativeFunction.hpp',
'src/NativeMacro.hpp',
'src/opcodes.hpp', 'src/opcodes.hpp',
'src/commons.hpp', 'src/commons.hpp',
'src/types.hpp', 'src/types.hpp',
@ -74,6 +76,7 @@ shared_library('fakir-std',
sources: [ sources: [
'libstd/lib.cpp', 'libstd/lib.cpp',
'libstd/fun.cpp', 'libstd/fun.cpp',
'libstd/macro.cpp',
], ],
dependencies: [ dependencies: [
fakir_dep fakir_dep

View File

@ -11,6 +11,12 @@ namespace fk
{ {
} }
void Compiler::add_macro(std::string const& name,
std::shared_ptr<NativeMacro> macro)
{
m_macros[name] = macro;
}
std::shared_ptr<Program> Compiler::compile(std::shared_ptr<Node> node) std::shared_ptr<Program> Compiler::compile(std::shared_ptr<Node> node)
{ {
auto prog = std::make_shared<Program>(); auto prog = std::make_shared<Program>();
@ -33,12 +39,22 @@ namespace fk
case NODE_CALL: { case NODE_CALL: {
std::string ident = node->child(0)->repr(); std::string ident = node->child(0)->repr();
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; i<node->size(); i++) for (size_t i=0; i<node->size(); i++)
{ {
compile_prog(node->child(i), prog); compile_prog(node->child(i), prog);
} }
prog->add(OP_CALL_NATIVE, node->size() - 1); prog->add(OP_CALL_NATIVE, node->size() - 1);
}
} break; } break;
case NODE_IDENT: { case NODE_IDENT: {

View File

@ -5,6 +5,7 @@
#include "Program.hpp" #include "Program.hpp"
#include "Node.hpp" #include "Node.hpp"
#include "SymTable.hpp" #include "SymTable.hpp"
#include "NativeMacro.hpp"
namespace fk namespace fk
{ {
@ -16,13 +17,19 @@ namespace fk
explicit Compiler(std::shared_ptr<SymTable> sym); explicit Compiler(std::shared_ptr<SymTable> sym);
virtual ~Compiler(); virtual ~Compiler();
std::shared_ptr<Program> compile(std::shared_ptr<Node> node); void add_macro(std::string const& name,
std::shared_ptr<NativeMacro> macro);
private: std::shared_ptr<Program> compile(std::shared_ptr<Node> node);
std::shared_ptr<SymTable> m_sym;
void compile_prog(std::shared_ptr<Node> node, void compile_prog(std::shared_ptr<Node> node,
std::shared_ptr<Program> prog); std::shared_ptr<Program> prog);
private:
std::shared_ptr<SymTable> m_sym;
std::unordered_map<std::string,
std::shared_ptr<NativeMacro>> m_macros;
}; };
} }

View File

@ -2,6 +2,7 @@
#include "conf.hpp" #include "conf.hpp"
#include "Module.hpp" #include "Module.hpp"
#include "Loc.hpp" #include "Loc.hpp"
#include "NativeMacro.hpp"
namespace fk namespace fk
{ {
@ -49,6 +50,12 @@ namespace fk
m_sym->declare_global(name, addr, Loc {"extern"}); m_sym->declare_global(name, addr, Loc {"extern"});
} }
void Module::register_macro(std::string const& name, macro_t macro)
{
auto m = std::make_shared<NativeMacro>(macro);
m_compiler->add_macro(name, m);
}
std::string Module::load_sources() std::string Module::load_sources()
{ {
std::ifstream file { m_source_path }; std::ifstream file { m_source_path };

View File

@ -24,6 +24,7 @@ namespace fk
void import_library(std::filesystem::path lib_path); void import_library(std::filesystem::path lib_path);
void register_function(std::string const& name, native_t native); void register_function(std::string const& name, native_t native);
void register_macro(std::string const& name, macro_t macro);
private: private:
std::filesystem::path m_source_path; std::filesystem::path m_source_path;

23
src/NativeMacro.cpp Normal file
View File

@ -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> node,
std::shared_ptr<Program> program)
{
m_macro(compiler, node, program);
}
}

30
src/NativeMacro.hpp Normal file
View File

@ -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<void(Compiler&,
std::shared_ptr<Node>,
std::shared_ptr<Program>)>;
class NativeMacro
{
public:
explicit NativeMacro(macro_t macro);
virtual ~NativeMacro();
void call(Compiler& compiler,
std::shared_ptr<Node> node,
std::shared_ptr<Program> program);
private:
macro_t m_macro;
};
}
#endif

View File

@ -5,10 +5,13 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
bool debug_mode = false;
while (true) while (true)
{ {
static struct option options[] = { static struct option options[] = {
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{"debug", no_argument, 0, 'd'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@ -34,6 +37,10 @@ int main(int argc, char** argv)
return 0; return 0;
} break; } break;
case 'd': {
debug_mode = true;
} break;
default: break; default: break;
} }
} }
@ -49,8 +56,24 @@ int main(int argc, char** argv)
if (sources.size()) if (sources.size())
{ {
fk::Module mod {sources[0]}; fk::Module mod {sources[0]};
if (debug_mode)
{
mod.build(); mod.build();
} }
else
{
try
{
mod.build();
}
catch(std::exception const& err)
{
std::cerr << err.what() << std::endl;
return -1;
}
}
}
return 0; return 0;
} }