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