ADD: vardecl.
parent
0aa9ebd952
commit
073cbb4618
|
@ -0,0 +1,7 @@
|
|||
(assert-fail a)
|
||||
($ a 34)
|
||||
(assert= 34 a)
|
||||
|
||||
($ b ($ c 9))
|
||||
(assert= 9 b)
|
||||
(assert= 9 c)
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,4 +20,5 @@ extern "C" void lib(Zarn& zarn)
|
|||
assert_eq);
|
||||
|
||||
zarn.register_macro("assert-fail", assert_fail);
|
||||
zarn.register_macro("$", declare);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace zn
|
|||
virtual ~StaticPass();
|
||||
|
||||
TypeSlot execute(Node const& node);
|
||||
|
||||
private:
|
||||
Logger& m_logger;
|
||||
SymTable& m_sym;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
44
src/VM.cpp
44
src/VM.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#define TYPES(G) \
|
||||
G(TYPE_NIL), \
|
||||
G(TYPE_INT), \
|
||||
G(TYPE_REF)
|
||||
G(TYPE_REF), \
|
||||
G(TYPE_FUNCTION)
|
||||
|
||||
namespace zn
|
||||
{
|
||||
|
|
Reference in New Issue