ADD: vardecl.

main
bog 2023-09-19 06:38:14 +02:00
parent 0aa9ebd952
commit 073cbb4618
12 changed files with 125 additions and 42 deletions

7
examples/vardecl.zn Normal file
View File

@ -0,0 +1,7 @@
(assert-fail a)
($ a 34)
(assert= 34 a)
($ b ($ c 9))
(assert= 9 b)
(assert= 9 c)

View File

@ -22,3 +22,18 @@ void assert_fail(Node const& node,
(TYPE_NIL, node.loc(), 0));
program.append(OPCODE_LOAD_CONST, addr);
}
void declare(Node const& node,
Compiler& compiler,
Program& program,
SymTable& sym)
{
std::string ident = node.child_at(1)->repr();
compiler.compile(*node.child_at(2), program);
auto entry = sym.find_any(ident);
assert(entry);
size_t addr = sym.gen_addr();
sym.declare(ident, addr);
program.append(OPCODE_STORE_LOCAL, addr);
}

View File

@ -8,4 +8,9 @@ void assert_fail(Node const& node,
Program& program,
SymTable& sym);
void declare(Node const& node,
Compiler& compiler,
Program& program,
SymTable& sym);
#endif

View File

@ -20,4 +20,5 @@ extern "C" void lib(Zarn& zarn)
assert_eq);
zarn.register_macro("assert-fail", assert_fail);
zarn.register_macro("$", declare);
}

View File

@ -100,13 +100,13 @@ namespace zn
{
auto ref = std::make_shared<Constant>(TYPE_REF,
node.loc(),
(int) sym->addr);
(int) *sym->addr);
size_t val = program.add_constant(ref);
program.append(OPCODE_LOAD_CONST, val);
}
else
{
program.append(OPCODE_LOAD_LOCAL, sym->addr);
program.append(OPCODE_LOAD_LOCAL, *sym->addr);
}
} break;

View File

@ -27,7 +27,17 @@ namespace zn
case NODE_CALL: {
std::string ident = node.child_at(0)->repr();
auto sym = m_sym.find(ident);
auto sym = m_sym.find_any(ident);
if (ident == "$")
{
std::string varname = node.child_at(1)->repr();
auto vartype = execute(*node.child_at(2));
//int index = m_sym.gen_addr();
m_sym.prepare(varname, *vartype.type);
return vartype;
}
if (sym == std::nullopt)
{
@ -75,6 +85,19 @@ namespace zn
return proto->get_ret();
} break;
case NODE_IDENT: {
std::string ident = node.repr();
auto sym = m_sym.find_any(ident);
if (sym == std::nullopt)
{
std::stringstream ss;
ss << "undeclared var '" << ident << "'";
m_logger.log<static_error>(LOG_ERROR, node.loc(), ss.str());
}
return TypeSlot {sym->type};
} break;
case NODE_INT: {
return TypeSlot {TYPE_INT};
} break;

View File

@ -17,6 +17,7 @@ namespace zn
virtual ~StaticPass();
TypeSlot execute(Node const& node);
private:
Logger& m_logger;
SymTable& m_sym;

View File

@ -10,19 +10,48 @@ namespace zn
{
}
void SymTable::prepare(std::string const& name, Type type)
{
m_syms.push_back(Sym {name, std::nullopt, type});
}
void SymTable::declare(std::string const& name, size_t addr)
{
m_syms.push_back(Sym {name, addr});
auto itr = std::find_if(std::begin(m_syms),
std::end(m_syms),
[name](auto const& sym){
return sym.name == name;
});
if (itr == std::end(m_syms))
{
abort();
}
itr->addr = addr;
}
void SymTable::declare_function(std::string const& name,
size_t addr,
std::shared_ptr<Prototype> prototype)
{
m_syms.push_back(Sym {name, addr, prototype});
m_syms.push_back(Sym {name, addr, TYPE_FUNCTION, prototype});
}
std::optional<Sym> SymTable::find(std::string const& name)
{
for (size_t i=0; i<m_syms.size(); i++)
{
if (name == m_syms[i].name && m_syms[i].addr != std::nullopt)
{
return m_syms[i];
}
}
return std::nullopt;
}
std::optional<Sym> SymTable::find_any(std::string const& name)
{
for (size_t i=0; i<m_syms.size(); i++)
{
@ -34,4 +63,11 @@ namespace zn
return std::nullopt;
}
size_t SymTable::gen_addr()
{
static size_t addr = 0;
addr++;
return addr;
}
}

View File

@ -8,7 +8,8 @@ namespace zn
{
struct Sym {
std::string name;
size_t addr;
std::optional<size_t> addr;
Type type;
std::shared_ptr<Prototype> prototype = nullptr;
};
@ -18,6 +19,9 @@ namespace zn
explicit SymTable();
virtual ~SymTable();
size_t size() const { return m_syms.size(); }
void prepare(std::string const& name, Type type);
void declare(std::string const& name, size_t addr);
void declare_function(std::string const& name,
@ -25,6 +29,9 @@ namespace zn
std::shared_ptr<Prototype> prototype);
std::optional<Sym> find(std::string const& name);
std::optional<Sym> find_any(std::string const& name);
size_t gen_addr();
private:
std::vector<Sym> m_syms;

View File

@ -35,8 +35,14 @@ namespace zn
} break;
case OPCODE_LOAD_LOCAL: {
auto constant = frame().locals[to_vm_addr(param)];
push(program.add_constant(constant));
auto constant = load_local(param);
size_t addr = program.add_constant(constant);
push(addr);
m_pc++;
} break;
case OPCODE_STORE_LOCAL: {
store_local(param, frame().program.constant(top()));
m_pc++;
} break;
@ -97,17 +103,14 @@ namespace zn
size_t VM::store_local(int index, std::shared_ptr<Constant> constant)
{
frame().locals.push_back(constant);
frame().locals[index] = constant;
size_t addr = frame().locals.size() - 1;
m_addr_mapping[index] = addr;
return addr;
}
std::shared_ptr<Constant> VM::load_local(int index) const
{
size_t addr = to_vm_addr(index);
assert(addr < m_frames.back().locals.size());
return m_frames.back().locals[addr];
return m_frames.back().locals.at(index);
}
size_t VM::store_global(global_var_t var)
@ -116,26 +119,6 @@ namespace zn
return m_globals.size() - 1;
}
size_t VM::to_vm_addr(int user_addr) const
{
return m_addr_mapping.at(user_addr);
}
int VM::to_user_addr(size_t vm_addr) const
{
for (auto const& entry: m_addr_mapping)
{
if (entry.second == vm_addr)
{
return entry.first;
}
}
std::cerr << "cannot find user addr of '"
<< vm_addr << "'" << std::endl;
abort();
}
Frame& VM::frame()
{
return m_frames.back();
@ -153,4 +136,11 @@ namespace zn
m_stack.pop_back();
return value;
}
int VM::top()
{
assert(m_stack.size() > 0);
int value = m_stack.back();
return value;
}
}

View File

@ -9,7 +9,7 @@ namespace zn
{
struct Frame {
Program& program;
std::vector<std::shared_ptr<Constant>> locals;
std::unordered_map<int, std::shared_ptr<Constant>> locals;
};
using global_var_t = std::variant<std::shared_ptr<NativeFunction>>;
@ -30,19 +30,16 @@ namespace zn
size_t store_global(global_var_t var);
size_t to_vm_addr(int user_addr) const;
int to_user_addr(size_t vm_addr) const;
private:
std::vector<Frame> m_frames;
std::vector<int> m_stack;
std::vector<global_var_t> m_globals;
std::unordered_map<int, size_t> m_addr_mapping;
size_t m_pc = 0;
Frame& frame();
void push(int value);
int pop();
int top();
};
}

View File

@ -3,10 +3,11 @@
#include "common.hpp"
#define TYPES(G) \
G(TYPE_NIL), \
G(TYPE_INT), \
G(TYPE_REF)
#define TYPES(G) \
G(TYPE_NIL), \
G(TYPE_INT), \
G(TYPE_REF), \
G(TYPE_FUNCTION)
namespace zn
{