ADD: var declaration.

main
bog 2023-09-10 08:06:34 +02:00
parent e8e4906cfc
commit 749f6c0a95
14 changed files with 136 additions and 22 deletions

View File

@ -3,4 +3,20 @@
extern "C" void lib(jk::Loader& loader) extern "C" void lib(jk::Loader& loader)
{ {
loader.declare("dump", [](auto args){
std::string sep;
for (auto arg: args)
{
std::cout << sep << arg->string();
sep = " ";
}
if (args.empty() == false)
{
std::cout << std::endl;
}
return jk::Value::make_nil();
});
} }

View File

@ -1,4 +1,8 @@
PROG ::= FUNCALL* PROG ::= FUNCALL*
EXPR ::= LITERAL | FUNCALL EXPR ::=
LITERAL
| FUNCALL
| VARDECL
VARDECL ::= opar decl ident EXPR cpar
FUNCALL ::= opar ident EXPR* cpar FUNCALL ::= opar ident EXPR* cpar
LITERAL ::= int | ident LITERAL ::= int | ident

View File

@ -36,18 +36,19 @@ namespace jk
program->push_instr(OPCODE_CALL, node->size() - 1); program->push_instr(OPCODE_CALL, node->size() - 1);
} break; } break;
case NODE_VARDECL: {
std::string ident = node->child(0).lock()->repr();
auto entry = m_sym->find(ident);
assert(entry);
compile(node->child(1).lock(), program);
program->push_instr(OPCODE_STORE, entry->addr);
} break;
case NODE_IDENT: { case NODE_IDENT: {
std::string ident = node->repr(); std::string ident = node->repr();
auto sym = m_sym->find(ident); auto sym = m_sym->find(ident);
assert(sym);
if (!sym)
{
m_logger.log<compile_error>(LOG_ERROR, node->loc(),
std::string()
+ "'"
+ ident
+ "' is undefined");
}
OpcodeType op_load = OPCODE_LOAD; OpcodeType op_load = OPCODE_LOAD;
@ -56,10 +57,7 @@ namespace jk
op_load = OPCODE_LOAD_GLOBAL; op_load = OPCODE_LOAD_GLOBAL;
} }
if (sym->type->type() == TYPE_FUNCTION) program->push_instr(op_load, sym->addr);
{
program->push_instr(op_load, sym->addr);
}
} break; } break;

View File

@ -7,6 +7,7 @@ namespace jk
, m_loc { loc } , m_loc { loc }
{ {
std::vector<std::tuple<NodeType, std::string, bool>> texts = { std::vector<std::tuple<NodeType, std::string, bool>> texts = {
{NODE_DECL, "$", false},
{NODE_OPAR, "(", false}, {NODE_OPAR, "(", false},
{NODE_CPAR, ")", false} {NODE_CPAR, ")", false}
}; };

View File

@ -10,7 +10,9 @@
G(NODE_OPAR), \ G(NODE_OPAR), \
G(NODE_CPAR), \ G(NODE_CPAR), \
G(NODE_IDENT), \ G(NODE_IDENT), \
G(NODE_FUNCALL), G(NODE_DECL), \
G(NODE_FUNCALL), \
G(NODE_VARDECL)
namespace jk namespace jk

View File

@ -91,7 +91,7 @@ namespace jk
while (m_cursor < m_tokens.size()) while (m_cursor < m_tokens.size())
{ {
root->add_child(parse_funcall()); root->add_child(parse_expr());
} }
return root; return root;
@ -99,14 +99,33 @@ namespace jk
std::shared_ptr<Node> Parser::parse_expr() std::shared_ptr<Node> Parser::parse_expr()
{ {
if (type_is(NODE_OPAR)) if (type_is(NODE_OPAR)
&& type_is(NODE_IDENT, 1))
{ {
return parse_funcall(); return parse_funcall();
} }
if (type_is(NODE_OPAR)
&& type_is(NODE_DECL, 1))
{
return parse_vardecl();
}
return parse_literal(); return parse_literal();
} }
std::shared_ptr<Node> Parser::parse_vardecl()
{
auto root = std::make_shared<Node>(NODE_VARDECL, "", loc());
consume(NODE_OPAR);
consume(NODE_DECL);
root->add_child(consume(NODE_IDENT));
root->add_child(parse_expr());
consume(NODE_CPAR);
return root;
}
std::shared_ptr<Node> Parser::parse_funcall() std::shared_ptr<Node> Parser::parse_funcall()
{ {
auto root = std::make_shared<Node>(NODE_FUNCALL, "", loc()); auto root = std::make_shared<Node>(NODE_FUNCALL, "", loc());
@ -134,8 +153,10 @@ namespace jk
loc(), loc(),
std::string() std::string()
+ "unexpected token '" + "unexpected token '"
+ NodeTypeStr[current()->type()]
+ "' ('"
+ current()->repr() + current()->repr()
+ "'"); + "')");
abort(); abort();
} }

View File

@ -31,6 +31,7 @@ namespace jk
std::shared_ptr<Node> parse_prog(); std::shared_ptr<Node> parse_prog();
std::shared_ptr<Node> parse_expr(); std::shared_ptr<Node> parse_expr();
std::shared_ptr<Node> parse_vardecl();
std::shared_ptr<Node> parse_funcall(); std::shared_ptr<Node> parse_funcall();
std::shared_ptr<Node> parse_literal(); std::shared_ptr<Node> parse_literal();
}; };

View File

@ -21,11 +21,46 @@ namespace jk
for (size_t i=0; i<node->size(); i++) for (size_t i=0; i<node->size(); i++)
{ {
pass(node->child(i).lock()); pass(node->child(i).lock());
pop();
} }
} break; } break;
case NODE_FUNCALL: { case NODE_INT: {
push(std::make_shared<Type>(TYPE_INT));
} break;
case NODE_IDENT: {
std::string ident = node->repr();
auto entry = m_sym->find(ident);
if (!entry)
{
m_logger.log<symbolic_error>(LOG_ERROR, node->loc(),
std::string()
+ "'"
+ ident
+ "' is undefined");
}
push(entry->type);
} break;
case NODE_VARDECL: {
std::string ident = node->child(0).lock()->repr();
pass(node->child(1).lock());
auto type = pop();
m_sym->declare(ident, type, node->loc());
push(type);
} break;
case NODE_FUNCALL: {
for (size_t i=0; i<node->size(); i++)
{
pass(node->child(i).lock());
pop();
}
// TODO find actual returned type
push(std::make_shared<Type>(TYPE_NIL));
} break; } break;
default: default:
@ -34,4 +69,17 @@ namespace jk
abort(); abort();
} }
} }
void StaticPass::push(std::shared_ptr<Type> type)
{
m_types.push_back(type);
}
std::shared_ptr<Type> StaticPass::pop()
{
auto type = m_types.back();
m_types.pop_back();
return type;
}
} }

View File

@ -18,6 +18,10 @@ namespace jk
private: private:
std::shared_ptr<SymTable> m_sym; std::shared_ptr<SymTable> m_sym;
Logger& m_logger; Logger& m_logger;
std::vector<std::shared_ptr<Type>> m_types;
void push(std::shared_ptr<Type> type);
std::shared_ptr<Type> pop();
}; };
} }

View File

@ -137,5 +137,4 @@ namespace jk
m_stack.pop_back(); m_stack.pop_back();
return param; return param;
} }
} }

View File

@ -68,6 +68,7 @@ namespace jk
{ {
case TYPE_NIL: return "<nil>"; case TYPE_NIL: return "<nil>";
case TYPE_INT: return std::to_string(*m_int_val); case TYPE_INT: return std::to_string(*m_int_val);
case TYPE_REF: return "<ref:" + std::to_string(*m_ref_val) + ">";
default: default:
std::cerr << "cannot stringify value '" std::cerr << "cannot stringify value '"

View File

@ -83,8 +83,6 @@ int main(int argc, char** argv)
auto sym = std::make_shared<jk::SymTable>(logger); auto sym = std::make_shared<jk::SymTable>(logger);
auto static_pass = std::make_shared<jk::StaticPass>(sym, logger);
static_pass->pass(ast);
auto compiler = std::make_shared<jk::Compiler>(sym, logger); auto compiler = std::make_shared<jk::Compiler>(sym, logger);
auto program = std::make_shared<jk::Program>(); auto program = std::make_shared<jk::Program>();
@ -92,6 +90,9 @@ int main(int argc, char** argv)
auto loader = std::make_shared<jk::Loader>(vm, sym); auto loader = std::make_shared<jk::Loader>(vm, sym);
loader->load(); loader->load();
auto static_pass = std::make_shared<jk::StaticPass>(sym, logger);
static_pass->pass(ast);
compiler->compile(ast, program); compiler->compile(ast, program);
if (debug_mode) if (debug_mode)

View File

@ -65,3 +65,11 @@ TEST_CASE_METHOD(LexerTest, "Lexer_funcall")
test_next(*lexer, "IDENT[salut/monde]"); test_next(*lexer, "IDENT[salut/monde]");
test_end(*lexer); test_end(*lexer);
} }
TEST_CASE_METHOD(LexerTest, "Lexer_vardecl")
{
auto lexer = jk::Factory(m_logger, "tests/lexer").make_lexer();
lexer->scan(" $ ");
test_next(*lexer, "DECL");
test_end(*lexer);
}

View File

@ -34,3 +34,13 @@ TEST_CASE_METHOD(ParserTest, "Parser_funcall")
test_parser("PROG(FUNCALL(IDENT[hello],INT[1],INT[2],IDENT[bim!]))", test_parser("PROG(FUNCALL(IDENT[hello],INT[1],INT[2],IDENT[bim!]))",
" (hello 1 2 bim!) "); " (hello 1 2 bim!) ");
} }
TEST_CASE_METHOD(ParserTest, "Parser_vardecl")
{
test_parser("PROG(VARDECL(IDENT[hello],INT[4]))",
" ($ hello 4) ");
test_parser("PROG(VARDECL(IDENT[world],"
"FUNCALL(IDENT[f],INT[3],INT[2])))",
" ($ world (f 3 2)) ");
}