ADD: blocks.
parent
820d26491a
commit
f63cbf4cea
|
@ -0,0 +1,20 @@
|
|||
($ a 2)
|
||||
(assert= 2 a)
|
||||
|
||||
(:
|
||||
($ a 9)
|
||||
(assert= 9 a)
|
||||
|
||||
(:
|
||||
($ a 42)
|
||||
(assert= 42 a)
|
||||
)
|
||||
|
||||
(assert= 9 a)
|
||||
)
|
||||
|
||||
(assert= 2 a)
|
||||
|
||||
(:($ b 43))
|
||||
|
||||
(assert-fail b)
|
|
@ -5,4 +5,4 @@
|
|||
|
||||
($ b ($ c 9))
|
||||
(assert= 9 b)
|
||||
(assert= 9 c)
|
||||
(assert= 9 c)
|
||||
|
|
|
@ -6,6 +6,7 @@ void assert_fail(Node const& node, Module& mod)
|
|||
{
|
||||
mod.static_pass().execute(*node.child_at(1));
|
||||
mod.compiler().compile(*node.child_at(1), mod.program());
|
||||
|
||||
Loc loc = node.loc();
|
||||
|
||||
std::cerr << loc.file_path().string() << ":" << loc.line();
|
||||
|
@ -29,6 +30,25 @@ void declare(Node const& node, Module &mod)
|
|||
assert(entry);
|
||||
size_t addr = mod.sym().gen_addr();
|
||||
|
||||
mod.sym().declare(ident, addr);
|
||||
mod.sym().declare(ident, addr, entry->scope);
|
||||
mod.program().append(OPCODE_STORE_LOCAL, addr);
|
||||
}
|
||||
|
||||
void block(Node const& node, Module& mod)
|
||||
{
|
||||
mod.sym().enter_scope();
|
||||
|
||||
for (size_t i=1; i<node.size(); i++)
|
||||
{
|
||||
mod.static_pass().execute(*node.child_at(i));
|
||||
mod.compiler().compile(*node.child_at(i), mod.program());
|
||||
|
||||
if (i != node.size() - 1)
|
||||
{
|
||||
mod.program().append(OPCODE_POP);
|
||||
}
|
||||
}
|
||||
|
||||
mod.sym().leave_scope();
|
||||
|
||||
}
|
||||
|
|
|
@ -7,4 +7,6 @@ void assert_fail(Node const& node, Module& mod);
|
|||
|
||||
void declare(Node const& node, Module& mod);
|
||||
|
||||
void block(Node const& node, Module& mod);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,4 +21,5 @@ extern "C" void lib(Zarn& zarn)
|
|||
|
||||
zarn.register_macro("assert-fail", assert_fail);
|
||||
zarn.register_macro("$", declare);
|
||||
zarn.register_macro(":", block);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,10 @@ namespace zn
|
|||
{
|
||||
case TYPE_NIL: return "<nil>";
|
||||
case TYPE_INT: return std::to_string(std::get<int>(*m_value));
|
||||
case TYPE_REF: {
|
||||
return "<ref " + std::to_string(std::get<int>(*m_value)) + ">";
|
||||
} break;
|
||||
|
||||
default: {
|
||||
std::cerr << "cannot stringify "
|
||||
<< (TypeStr[m_type] + strlen("TYPE_"))
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace zn
|
|||
case NODE_IDENT: {
|
||||
std::string ident = node.repr();
|
||||
auto sym = m_sym.find_any(ident);
|
||||
|
||||
if (sym) assert(sym->scope <= m_sym.scope());
|
||||
if (sym == std::nullopt)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -12,15 +12,18 @@ namespace zn
|
|||
|
||||
void SymTable::prepare(std::string const& name, Type type)
|
||||
{
|
||||
m_syms.push_back(Sym {name, std::nullopt, type});
|
||||
m_syms.push_back(Sym {name, std::nullopt, type, nullptr, m_scope});
|
||||
}
|
||||
|
||||
void SymTable::declare(std::string const& name, size_t addr)
|
||||
void SymTable::declare(std::string const& name,
|
||||
size_t addr,
|
||||
int scope)
|
||||
{
|
||||
auto itr = std::find_if(std::begin(m_syms),
|
||||
std::end(m_syms),
|
||||
[name](auto const& sym){
|
||||
return sym.name == name;
|
||||
[name, scope](auto const& sym){
|
||||
return sym.name == name
|
||||
&& sym.scope == scope;
|
||||
});
|
||||
|
||||
if (itr == std::end(m_syms))
|
||||
|
@ -28,39 +31,61 @@ namespace zn
|
|||
abort();
|
||||
}
|
||||
|
||||
itr->addr = addr;
|
||||
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, TYPE_FUNCTION, prototype});
|
||||
m_syms.push_back(Sym {name, addr, TYPE_FUNCTION, prototype, m_scope});
|
||||
}
|
||||
|
||||
std::optional<Sym> SymTable::find(std::string const& name)
|
||||
{
|
||||
std::optional<size_t> best;
|
||||
|
||||
for (size_t i=0; i<m_syms.size(); i++)
|
||||
{
|
||||
if (name == m_syms[i].name && m_syms[i].addr != std::nullopt)
|
||||
if (name == m_syms[i].name
|
||||
&& m_syms[i].addr
|
||||
&& (best == std::nullopt ||
|
||||
(m_syms[i].scope > m_syms[*best].scope
|
||||
&& m_syms[*best].scope < m_scope)))
|
||||
{
|
||||
return m_syms[i];
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (best)
|
||||
{
|
||||
return m_syms[*best];
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<Sym> SymTable::find_any(std::string const& name)
|
||||
{
|
||||
std::optional<size_t> best;
|
||||
|
||||
for (size_t i=0; i<m_syms.size(); i++)
|
||||
{
|
||||
if (name == m_syms[i].name)
|
||||
if (name == m_syms[i].name
|
||||
&& m_syms[i].scope <= m_scope
|
||||
&& (best == std::nullopt ||
|
||||
(m_syms[i].scope > m_syms[*best].scope
|
||||
&& m_syms[*best].scope <= m_scope)))
|
||||
{
|
||||
return m_syms[i];
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (best)
|
||||
{
|
||||
return m_syms[*best];
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
@ -70,4 +95,30 @@ namespace zn
|
|||
addr++;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void SymTable::enter_scope()
|
||||
{
|
||||
m_scope++;
|
||||
}
|
||||
|
||||
void SymTable::leave_scope()
|
||||
{
|
||||
m_scope--;
|
||||
}
|
||||
|
||||
std::string SymTable::string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "======== " << m_scope << " ========\n";
|
||||
|
||||
for (auto sym: m_syms)
|
||||
{
|
||||
ss << sym.scope << "\t" << sym.name << " "
|
||||
<< (sym.addr ? "[" + std::to_string(*sym.addr) + "]" : "[nil]")
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "common.hpp"
|
||||
#include "Prototype.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace zn
|
||||
{
|
||||
|
@ -11,6 +12,7 @@ namespace zn
|
|||
std::optional<size_t> addr;
|
||||
Type type;
|
||||
std::shared_ptr<Prototype> prototype = nullptr;
|
||||
int scope = 0;
|
||||
};
|
||||
|
||||
class SymTable
|
||||
|
@ -19,10 +21,13 @@ namespace zn
|
|||
explicit SymTable();
|
||||
virtual ~SymTable();
|
||||
|
||||
int scope() const { return m_scope; }
|
||||
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(std::string const& name,
|
||||
size_t addr,
|
||||
int scope);
|
||||
|
||||
void declare_function(std::string const& name,
|
||||
size_t addr,
|
||||
|
@ -33,8 +38,13 @@ namespace zn
|
|||
|
||||
size_t gen_addr();
|
||||
|
||||
void enter_scope();
|
||||
void leave_scope();
|
||||
|
||||
std::string string() const;
|
||||
private:
|
||||
std::vector<Sym> m_syms;
|
||||
int m_scope = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Reference in New Issue