ADD: global variable declaration (mutable or not).
parent
66283e23bb
commit
b9072c580f
|
@ -2,7 +2,14 @@ PROG ::= (INSTR (EOI+ INSTR)*)?
|
|||
|
||||
INSTR ::= EXPR
|
||||
| assert EXPR
|
||||
| assert_static_fail EXPR
|
||||
| assert_static_fail INSTR
|
||||
| VARDECL
|
||||
| CONSTDECL
|
||||
| ASSIGN
|
||||
|
||||
VARDECL ::= let_mut ident assign EXPR
|
||||
CONSTDECL ::= let ident assign EXPR
|
||||
ASSIGN ::= ident assign EXPR
|
||||
|
||||
EXPR ::= IMP
|
||||
|
||||
|
@ -19,4 +26,4 @@ FACTOR ::= UNOP ((mul | div | mod) UNOP)*
|
|||
UNOP ::= (add | sub | not)? POW
|
||||
POW ::= GROUP (pow GROUP)?
|
||||
GROUP ::= BASE | opar EXPR cpar
|
||||
BASE ::= int | bool
|
||||
BASE ::= int | bool | ident
|
||||
|
|
|
@ -35,8 +35,9 @@ namespace roza
|
|||
|
||||
try
|
||||
{
|
||||
StaticPass static_pass {m_log};
|
||||
StaticPass static_pass {m_log, m_sym};
|
||||
static_pass.check_children(root);
|
||||
|
||||
compile_children(root, prog);
|
||||
|
||||
failed = true;
|
||||
|
@ -52,6 +53,33 @@ namespace roza
|
|||
|
||||
} break;
|
||||
|
||||
case NODE_IDENT: {
|
||||
SymEntry const& entry = m_sym.find(root->repr());
|
||||
prog->push_instr(OP_LOAD_GLOBAL, entry.addr);
|
||||
} break;
|
||||
|
||||
case NODE_VARDECL: {
|
||||
std::string name = root->child(0)->repr();
|
||||
compile_node(root->child(1), prog);
|
||||
int addr = m_sym.declare_mut(name, root->child(1));
|
||||
prog->push_instr(OP_STORE_GLOBAL, addr);
|
||||
|
||||
} break;
|
||||
|
||||
case NODE_CONSTDECL: {
|
||||
std::string name = root->child(0)->repr();
|
||||
compile_node(root->child(1), prog);
|
||||
int addr = m_sym.declare(name, root->child(1));
|
||||
prog->push_instr(OP_STORE_GLOBAL, addr);
|
||||
|
||||
} break;
|
||||
|
||||
case NODE_ASSIGN: {
|
||||
int addr = m_sym.find(root->child(0)->repr()).addr;
|
||||
compile_node(root->child(1), prog);
|
||||
prog->push_instr(OP_STORE_GLOBAL, addr);
|
||||
} break;
|
||||
|
||||
case NODE_INT: {
|
||||
auto value = std::make_shared<Value>(std::stoi(root->repr()), root->loc());
|
||||
prog->push_instr(OP_PUSH_CONST, prog->push_value(value));
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Node.hpp"
|
||||
#include "opcodes.hpp"
|
||||
#include "StatusLog.hpp"
|
||||
#include "SymTable.hpp"
|
||||
|
||||
namespace roza
|
||||
{
|
||||
|
@ -21,6 +22,7 @@ namespace roza
|
|||
|
||||
private:
|
||||
StatusLog& m_log;
|
||||
SymTable m_sym;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,12 @@ namespace roza
|
|||
{"^", NODE_POW, false},
|
||||
{"(", NODE_OPAR, false},
|
||||
{")", NODE_CPAR, false},
|
||||
{"=", NODE_ASSIGN, false},
|
||||
};
|
||||
|
||||
std::vector<std::tuple<std::string, NodeType, bool>> keywords = {
|
||||
{"let!", NODE_LET_MUT, false},
|
||||
{"let", NODE_LET, false},
|
||||
{"true", NODE_BOOL, true},
|
||||
{"false", NODE_BOOL, true},
|
||||
{"and", NODE_AND, false},
|
||||
|
@ -35,7 +38,6 @@ namespace roza
|
|||
{"assert", NODE_ASSERT, false},
|
||||
};
|
||||
|
||||
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_int, this));
|
||||
|
||||
for (auto const& entry: keywords)
|
||||
|
@ -54,6 +56,7 @@ namespace roza
|
|||
std::get<2>(entry)));
|
||||
}
|
||||
|
||||
m_scanners.push_back(std::bind(&Lexer::scan_ident, this));
|
||||
}
|
||||
|
||||
/*virtual*/ Lexer::~Lexer()
|
||||
|
@ -225,4 +228,42 @@ namespace roza
|
|||
};
|
||||
}
|
||||
|
||||
ScanInfo Lexer::scan_ident() const
|
||||
{
|
||||
size_t cursor = m_cursor;
|
||||
std::string value;
|
||||
|
||||
auto is_ident = [](size_t pos, char c){
|
||||
bool other = false;
|
||||
|
||||
if (pos > 0)
|
||||
{
|
||||
other =
|
||||
std::isdigit(c);
|
||||
}
|
||||
|
||||
return c == '_' || std::isalpha(c) || other;
|
||||
};
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
while (cursor < m_source.size()
|
||||
&& is_ident(pos, m_source[cursor]))
|
||||
{
|
||||
value += m_source[cursor];
|
||||
cursor++;
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (value.empty() == false)
|
||||
{
|
||||
return ScanInfo {
|
||||
std::make_shared<Node>(NODE_IDENT, value, loc()),
|
||||
cursor
|
||||
};
|
||||
}
|
||||
|
||||
return ScanInfo {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace roza
|
|||
ScanInfo scan_keyword(std::string const& keyword,
|
||||
NodeType type,
|
||||
bool value=false) const;
|
||||
|
||||
ScanInfo scan_ident() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
G(NODE_CPAR), G(NODE_UADD), G(NODE_USUB), G(NODE_BOOL), \
|
||||
G(NODE_AND), G(NODE_OR), G(NODE_NOT), G(NODE_IMP), \
|
||||
G(NODE_EQ), G(NODE_NE), G(NODE_LT), G(NODE_LE), G(NODE_GT), \
|
||||
G(NODE_GE), G(NODE_ASSERT), G(NODE_ASSERT_STATIC_FAIL)
|
||||
G(NODE_GE), G(NODE_ASSERT), G(NODE_ASSERT_STATIC_FAIL), \
|
||||
G(NODE_IDENT), G(NODE_ASSIGN), G(NODE_LET), G(NODE_LET_MUT), \
|
||||
G(NODE_VARDECL), G(NODE_CONSTDECL)
|
||||
|
||||
namespace roza
|
||||
{
|
||||
|
|
|
@ -94,6 +94,12 @@ namespace roza
|
|||
return ret;
|
||||
}
|
||||
|
||||
void Parser::ensure(NodeType type)
|
||||
{
|
||||
consume_or_nullptr(type);
|
||||
consume_all(type);
|
||||
}
|
||||
|
||||
void Parser::next()
|
||||
{
|
||||
m_cursor++;
|
||||
|
@ -121,22 +127,88 @@ namespace roza
|
|||
{
|
||||
consume_all(NODE_EOI);
|
||||
|
||||
std::shared_ptr<Node> root;
|
||||
|
||||
if (type_is(NODE_ASSERT)
|
||||
|| type_is(NODE_ASSERT_STATIC_FAIL))
|
||||
if (type_is(NODE_ASSERT))
|
||||
{
|
||||
root = consume();
|
||||
auto root = consume();
|
||||
root->add_child(parse_expr());
|
||||
|
||||
ensure(NODE_EOI);
|
||||
return root;
|
||||
}
|
||||
else if (type_is(NODE_ASSERT_STATIC_FAIL))
|
||||
{
|
||||
auto root = consume();
|
||||
root->add_child(parse_instr());
|
||||
return root;
|
||||
}
|
||||
else if (type_is(NODE_LET))
|
||||
{
|
||||
auto root = parse_constdecl();
|
||||
ensure(NODE_EOI);
|
||||
return root;
|
||||
}
|
||||
else if (type_is(NODE_LET_MUT))
|
||||
{
|
||||
auto root = parse_vardecl();
|
||||
ensure(NODE_EOI);
|
||||
return root;
|
||||
}
|
||||
else if (type_is(NODE_IDENT) && type_is(NODE_ASSIGN, 1))
|
||||
{
|
||||
auto root = parse_assign();
|
||||
ensure(NODE_EOI);
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = parse_expr();
|
||||
auto root = parse_expr();
|
||||
ensure(NODE_EOI);
|
||||
return root;
|
||||
}
|
||||
|
||||
m_log.fatal(node()->loc(),
|
||||
std::string()
|
||||
+ "unknown instruction '"
|
||||
+ std::string(NodeTypeStr[node()->type()])
|
||||
.substr(std::string("NODE_").size())
|
||||
+ "'");
|
||||
|
||||
consume_or_nullptr(NODE_EOI);
|
||||
consume_all(NODE_EOI);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_vardecl()
|
||||
{
|
||||
consume(NODE_LET_MUT);
|
||||
auto root = std::make_shared<Node>(NODE_VARDECL, "", node()->loc());
|
||||
auto ident = consume(NODE_IDENT);
|
||||
consume(NODE_ASSIGN);
|
||||
auto expr = parse_expr();
|
||||
root->add_child(ident);
|
||||
root->add_child(expr);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_constdecl()
|
||||
{
|
||||
consume(NODE_LET);
|
||||
auto root = std::make_shared<Node>(NODE_CONSTDECL, "", node()->loc());
|
||||
auto ident = consume(NODE_IDENT);
|
||||
consume(NODE_ASSIGN);
|
||||
auto expr = parse_expr();
|
||||
root->add_child(ident);
|
||||
root->add_child(expr);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
std::shared_ptr<Node> Parser::parse_assign()
|
||||
{
|
||||
auto lhs = consume(NODE_IDENT);
|
||||
auto root = consume(NODE_ASSIGN);
|
||||
|
||||
root->add_child(lhs);
|
||||
root->add_child(parse_expr());
|
||||
|
||||
return root;
|
||||
}
|
||||
|
@ -320,13 +392,14 @@ namespace roza
|
|||
std::shared_ptr<Node> Parser::parse_base()
|
||||
{
|
||||
if (type_is(NODE_INT)
|
||||
|| type_is(NODE_BOOL))
|
||||
|| type_is(NODE_BOOL)
|
||||
|| type_is(NODE_IDENT))
|
||||
{
|
||||
return consume();
|
||||
}
|
||||
|
||||
m_log.fatal(node()->loc(),
|
||||
"unknown node '"
|
||||
"cannot parse unknown node '"
|
||||
+ node()->string()
|
||||
+ "'");
|
||||
|
||||
|
|
|
@ -27,10 +27,16 @@ namespace roza
|
|||
std::shared_ptr<Node> consume(NodeType type);
|
||||
void consume_all(NodeType type);
|
||||
std::shared_ptr<Node> consume();
|
||||
void ensure(NodeType type);
|
||||
void next();
|
||||
|
||||
std::shared_ptr<Node> parse_prog();
|
||||
std::shared_ptr<Node> parse_instr();
|
||||
|
||||
std::shared_ptr<Node> parse_vardecl();
|
||||
std::shared_ptr<Node> parse_constdecl();
|
||||
std::shared_ptr<Node> parse_assign();
|
||||
|
||||
std::shared_ptr<Node> parse_expr();
|
||||
std::shared_ptr<Node> parse_imp();
|
||||
std::shared_ptr<Node> parse_or();
|
||||
|
|
|
@ -5,7 +5,13 @@
|
|||
namespace roza
|
||||
{
|
||||
/*explicit*/ StaticPass::StaticPass(StatusLog& log)
|
||||
: StaticPass (log, SymTable {})
|
||||
{
|
||||
}
|
||||
|
||||
/*explicit*/ StaticPass::StaticPass(StatusLog& log, SymTable const& sym_table)
|
||||
: m_log { log }
|
||||
, m_sym { SymTable(sym_table) }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -16,9 +22,35 @@ namespace roza
|
|||
void StaticPass::check(std::shared_ptr<Node> root)
|
||||
{
|
||||
TypeResolver resolver {m_log};
|
||||
assert(root);
|
||||
|
||||
switch (root->type())
|
||||
{
|
||||
case NODE_CONSTDECL: {
|
||||
check(root->child(1));
|
||||
m_sym.declare(root->child(0)->repr(), root->child(1));
|
||||
} break;
|
||||
|
||||
case NODE_VARDECL: {
|
||||
check(root->child(1));
|
||||
m_sym.declare_mut(root->child(0)->repr(), root->child(1));
|
||||
} break;
|
||||
|
||||
case NODE_ASSIGN: {
|
||||
auto const& entry = m_sym.find(root->child(0)->repr());
|
||||
|
||||
if (!entry.is_mut)
|
||||
{
|
||||
m_log.fatal(root->child(0)->loc(),
|
||||
root->child(0)->repr() + " is not mutable");
|
||||
}
|
||||
|
||||
auto lhs = resolver.find(entry.node, m_sym);
|
||||
auto rhs = resolver.find(root->child(1), m_sym);
|
||||
check_types(root, lhs, rhs);
|
||||
} break;
|
||||
|
||||
case NODE_IDENT:
|
||||
case NODE_ASSERT_STATIC_FAIL:
|
||||
case NODE_INT:
|
||||
case NODE_BOOL:
|
||||
|
@ -27,8 +59,8 @@ namespace roza
|
|||
case NODE_EQ:
|
||||
case NODE_NE: {
|
||||
check_children(root);
|
||||
auto lhs = resolver.find(root->child(0));
|
||||
auto rhs = resolver.find(root->child(1));
|
||||
auto lhs = resolver.find(root->child(0), m_sym);
|
||||
auto rhs = resolver.find(root->child(1), m_sym);
|
||||
check_types(root, lhs, rhs);
|
||||
} break;
|
||||
|
||||
|
@ -36,8 +68,8 @@ namespace roza
|
|||
case NODE_OR:
|
||||
case NODE_AND: {
|
||||
check_children(root);
|
||||
auto lhs = resolver.find(root->child(0));
|
||||
auto rhs = resolver.find(root->child(1));
|
||||
auto lhs = resolver.find(root->child(0), m_sym);
|
||||
auto rhs = resolver.find(root->child(1), m_sym);
|
||||
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
|
||||
check_types(root, lhs, rhs);
|
||||
} break;
|
||||
|
@ -45,7 +77,7 @@ namespace roza
|
|||
case NODE_ASSERT:
|
||||
case NODE_NOT: {
|
||||
check_children(root);
|
||||
auto lhs = resolver.find(root->child(0));
|
||||
auto lhs = resolver.find(root->child(0), m_sym);
|
||||
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
|
||||
} break;
|
||||
|
||||
|
@ -60,8 +92,9 @@ namespace roza
|
|||
case NODE_MOD:
|
||||
case NODE_POW: {
|
||||
check_children(root);
|
||||
auto lhs = resolver.find(root->child(0));
|
||||
auto rhs = resolver.find(root->child(1));
|
||||
auto lhs = resolver.find(root->child(0), m_sym);
|
||||
auto rhs = resolver.find(root->child(1), m_sym);
|
||||
|
||||
check_types(root, lhs, std::make_shared<Type>(TY_INT));
|
||||
check_types(root, lhs, rhs);
|
||||
} break;
|
||||
|
@ -69,7 +102,7 @@ namespace roza
|
|||
case NODE_UADD:
|
||||
case NODE_USUB: {
|
||||
check_children(root);
|
||||
auto lhs = resolver.find(root->child(0));
|
||||
auto lhs = resolver.find(root->child(0), m_sym);
|
||||
check_types(root, lhs, std::make_shared<Type>(TY_INT));
|
||||
} break;
|
||||
|
||||
|
@ -94,6 +127,9 @@ namespace roza
|
|||
std::shared_ptr<Type> lhs,
|
||||
std::shared_ptr<Type> rhs)
|
||||
{
|
||||
assert(lhs);
|
||||
assert(rhs);
|
||||
|
||||
if (!lhs->equals(*rhs))
|
||||
{
|
||||
m_log.fatal(root->loc(),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "StatusLog.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "Type.hpp"
|
||||
#include "SymTable.hpp"
|
||||
|
||||
namespace roza
|
||||
{
|
||||
|
@ -12,6 +13,7 @@ namespace roza
|
|||
{
|
||||
public:
|
||||
explicit StaticPass(StatusLog& log);
|
||||
explicit StaticPass(StatusLog& log, SymTable const& sym_table);
|
||||
virtual ~StaticPass();
|
||||
|
||||
void check(std::shared_ptr<Node> root);
|
||||
|
@ -19,6 +21,7 @@ namespace roza
|
|||
|
||||
private:
|
||||
StatusLog& m_log;
|
||||
SymTable m_sym;
|
||||
|
||||
void check_types(std::shared_ptr<Node> root,
|
||||
std::shared_ptr<Type> lhs,
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#include "SymTable.hpp"
|
||||
|
||||
namespace roza
|
||||
{
|
||||
/*static*/ int SymTable::addr = 0;
|
||||
|
||||
/*explicit*/ SymTable::SymTable()
|
||||
{
|
||||
}
|
||||
|
||||
/*explicit*/ SymTable::SymTable(SymTable const& sym_table)
|
||||
{
|
||||
m_scope = sym_table.m_scope;
|
||||
|
||||
for (auto const& entry: sym_table.m_entries)
|
||||
{
|
||||
m_entries[entry.first] = entry.second;
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ SymTable::~SymTable()
|
||||
{
|
||||
}
|
||||
|
||||
int SymTable::declare(std::string const& name, std::shared_ptr<Node> node)
|
||||
{
|
||||
assert(!exists(name));
|
||||
|
||||
m_entries.insert({name, SymEntry {
|
||||
SymTable::addr++,
|
||||
m_scope,
|
||||
node,
|
||||
false
|
||||
}});
|
||||
|
||||
return SymTable::addr - 1;
|
||||
}
|
||||
|
||||
int SymTable::declare_mut(std::string const& name, std::shared_ptr<Node> node)
|
||||
{
|
||||
assert(!exists(name));
|
||||
|
||||
m_entries.insert({name, SymEntry {
|
||||
SymTable::addr++,
|
||||
m_scope,
|
||||
node,
|
||||
true
|
||||
}});
|
||||
|
||||
return SymTable::addr - 1;
|
||||
}
|
||||
|
||||
SymEntry& SymTable::find(std::string const& name)
|
||||
{
|
||||
assert(exists(name));
|
||||
return m_entries[name];
|
||||
}
|
||||
|
||||
SymEntry const& SymTable::find(std::string const& name) const
|
||||
{
|
||||
assert(exists(name));
|
||||
return m_entries.at(name);
|
||||
}
|
||||
|
||||
bool SymTable::exists(std::string const& name) const
|
||||
{
|
||||
return m_entries.find(name) != std::end(m_entries);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#ifndef roza_SYMTABLE_HPP
|
||||
#define roza_SYMTABLE_HPP
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "Node.hpp"
|
||||
|
||||
namespace roza
|
||||
{
|
||||
struct SymEntry {
|
||||
int addr;
|
||||
int scope;
|
||||
std::shared_ptr<Node> node;
|
||||
bool is_mut;
|
||||
};
|
||||
|
||||
class SymTable
|
||||
{
|
||||
public:
|
||||
explicit SymTable();
|
||||
explicit SymTable(SymTable const& sym_table);
|
||||
|
||||
virtual ~SymTable();
|
||||
|
||||
int declare(std::string const& name, std::shared_ptr<Node> node);
|
||||
int declare_mut(std::string const& name, std::shared_ptr<Node> node);
|
||||
|
||||
SymEntry& find(std::string const& name);
|
||||
SymEntry const& find(std::string const& name) const;
|
||||
|
||||
bool exists(std::string const& name) const;
|
||||
|
||||
private:
|
||||
static int addr;
|
||||
std::unordered_map<std::string, SymEntry> m_entries;
|
||||
int m_scope = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -11,12 +11,24 @@ namespace roza
|
|||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Type> TypeResolver::find(std::shared_ptr<Node> root)
|
||||
std::shared_ptr<Type> TypeResolver::find(std::shared_ptr<Node> root,
|
||||
SymTable const& sym)
|
||||
{
|
||||
switch (root->type())
|
||||
{
|
||||
case NODE_PROG: {
|
||||
return find(root->child(root->size() - 1));
|
||||
return find(root->child(root->size() - 1), sym);
|
||||
} break;
|
||||
|
||||
case NODE_IDENT: {
|
||||
std::string name = root->repr();
|
||||
SymEntry const& entry = sym.find(name);
|
||||
return find(entry.node, sym);
|
||||
} break;
|
||||
|
||||
case NODE_CONSTDECL:
|
||||
case NODE_VARDECL: {
|
||||
auto ty = find(root->child(1), sym);
|
||||
} break;
|
||||
|
||||
case NODE_INT: {
|
||||
|
@ -45,7 +57,7 @@ namespace roza
|
|||
case NODE_POW:
|
||||
case NODE_UADD:
|
||||
case NODE_USUB:{
|
||||
return find(root->child(0));
|
||||
return find(root->child(0), sym);
|
||||
} break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "Type.hpp"
|
||||
#include "StatusLog.hpp"
|
||||
#include "Node.hpp"
|
||||
#include "SymTable.hpp"
|
||||
|
||||
namespace roza
|
||||
{
|
||||
|
@ -14,7 +15,7 @@ namespace roza
|
|||
explicit TypeResolver(StatusLog& log);
|
||||
virtual ~TypeResolver();
|
||||
|
||||
std::shared_ptr<Type> find(std::shared_ptr<Node> root);
|
||||
std::shared_ptr<Type> find(std::shared_ptr<Node> root, SymTable const& sym);
|
||||
private:
|
||||
StatusLog& m_log;
|
||||
};
|
||||
|
|
17
lib/VM.cpp
17
lib/VM.cpp
|
@ -19,6 +19,23 @@ namespace roza
|
|||
{
|
||||
switch (program->opcode(m_pc))
|
||||
{
|
||||
case OP_LOAD_GLOBAL: {
|
||||
int addr = *program->param(m_pc);
|
||||
auto value = m_globals[addr];
|
||||
push(program->push_value(value));
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OP_STORE_GLOBAL: {
|
||||
auto value = program->value(pop());
|
||||
int addr = *program->param(m_pc);
|
||||
|
||||
m_globals[addr] = value;
|
||||
|
||||
m_pc++;
|
||||
} break;
|
||||
|
||||
case OP_ASSERT: {
|
||||
auto value = program->value(pop());
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace roza
|
|||
StatusLog& m_log;
|
||||
std::vector<param_t> m_stack;
|
||||
std::shared_ptr<Program> m_last_program;
|
||||
std::unordered_map<int, std::shared_ptr<Value>> m_globals;
|
||||
size_t m_pc = 0;
|
||||
|
||||
void push(param_t param);
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
G(OP_POP), \
|
||||
G(OP_IADD), G(OP_ISUB), G(OP_IMUL), G(OP_IDIV), G(OP_IMOD), G(OP_IPOW), \
|
||||
G(OP_MOD), G(OP_IUADD), G(OP_IUSUB), G(OP_AND), G(OP_OR), G(OP_NOT), \
|
||||
G(OP_IMP), G(OP_EQ), G(OP_ILT), G(OP_IGT), G(OP_ASSERT)
|
||||
G(OP_IMP), G(OP_EQ), G(OP_ILT), G(OP_IGT), G(OP_ASSERT), G(OP_STORE_GLOBAL), \
|
||||
G(OP_LOAD_GLOBAL)
|
||||
|
||||
namespace roza
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ roza_lib = static_library(
|
|||
'lib/Type.cpp',
|
||||
'lib/Value.cpp',
|
||||
'lib/TypeResolver.cpp',
|
||||
'lib/SymTable.cpp',
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
let! a = 34
|
||||
|
||||
assert 34 == a
|
||||
assert 102 == 3 * a
|
||||
|
||||
a = 9
|
||||
|
||||
a = a + 1
|
||||
|
||||
assert 11 == a + 1
|
||||
|
||||
assert_static_fail a and true
|
||||
assert_static_fail a = false
|
||||
|
||||
let b = 7
|
||||
|
||||
assert 7 == b
|
||||
assert 42 == 6 * b
|
||||
assert 17 == a + b
|
||||
|
||||
assert_static_fail b = 4
|
|
@ -58,7 +58,6 @@ TEST_CASE_METHOD(LexerTest, "Lexer_int_arith")
|
|||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_keywords")
|
||||
{
|
||||
REQUIRE_THROWS(m_lexer.scan(" andor "));
|
||||
REQUIRE_NOTHROW(m_lexer.scan(" and+ "));
|
||||
REQUIRE_NOTHROW(m_lexer.scan(" (and) "));
|
||||
}
|
||||
|
@ -94,3 +93,13 @@ TEST_CASE_METHOD(LexerTest, "Lexer_asserts")
|
|||
REQUIRE("ASSERT_STATIC_FAIL" == get_str(1));
|
||||
REQUIRE("" == get_str(2));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(LexerTest, "Lexer_declarations")
|
||||
{
|
||||
m_lexer.scan(" let let! hello = ");
|
||||
REQUIRE("LET" == get_str(0));
|
||||
REQUIRE("LET_MUT" == get_str(1));
|
||||
REQUIRE("IDENT[hello]" == get_str(2));
|
||||
REQUIRE("ASSIGN" == get_str(3));
|
||||
REQUIRE("" == get_str(4));
|
||||
}
|
||||
|
|
|
@ -110,3 +110,15 @@ TEST_CASE_METHOD(ParserTest, "Parser_assertions")
|
|||
test_node("PROG(ASSERT_STATIC_FAIL(EQ(ADD(INT[1],INT[1]),INT[2])))",
|
||||
"assert_static_fail 1 + 1 == 2");
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(ParserTest, "Parser_vardecl")
|
||||
{
|
||||
test_node("PROG(VARDECL(IDENT[x],INT[34]))",
|
||||
"let! x = 34");
|
||||
|
||||
test_node("PROG(CONSTDECL(IDENT[x],INT[34]))",
|
||||
"let x = 34");
|
||||
|
||||
test_node("PROG(CONSTDECL(IDENT[_coucou],MUL(INT[6],INT[7])))",
|
||||
"let _coucou = 6 * 7");
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@ public:
|
|||
roza::StatusLog log;
|
||||
roza::Lexer lexer {log, loc};
|
||||
roza::Parser parser {lexer, log};
|
||||
roza::SymTable sym;
|
||||
roza::TypeResolver resolver {log};
|
||||
|
||||
lexer.scan(source);
|
||||
auto node = parser.parse();
|
||||
return resolver.find(node);
|
||||
return resolver.find(node, sym);
|
||||
}
|
||||
|
||||
void test_ty(std::string const& source, std::shared_ptr<roza::Type> ty)
|
||||
|
|
Loading…
Reference in New Issue