Improvements on the evaluator
This commit is contained in:
@@ -1,46 +1,5 @@
|
|||||||
|
if 1 == 2: {
|
||||||
let title = "My Website"
|
let a = 1
|
||||||
|
} else {
|
||||||
let posts = [
|
let b =
|
||||||
{
|
}
|
||||||
name: "Post Title 1",
|
|
||||||
date: "1 Jan 2025",
|
|
||||||
comments: [
|
|
||||||
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
|
||||||
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Post Title 2",
|
|
||||||
date: "4 July 2022",
|
|
||||||
comments: [
|
|
||||||
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
|
||||||
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
|
||||||
]
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
fun render_comment(c)
|
|
||||||
<div class="comment">
|
|
||||||
<a>\c.author (\c.date)</a>
|
|
||||||
<p>\c.content</p>
|
|
||||||
<div class="comment-children">
|
|
||||||
\for child in c.children:
|
|
||||||
render_comment(child)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>\title</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<a>This is regular text</a>
|
|
||||||
\for post in posts:
|
|
||||||
<div class="post">
|
|
||||||
<a>\post.title (\post.date)</a>
|
|
||||||
\for comment in post.comments:
|
|
||||||
render_comment(comment)
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
let title = "My Website"
|
||||||
|
|
||||||
|
let posts = [
|
||||||
|
{
|
||||||
|
name: "Post Title 1",
|
||||||
|
date: "1 Jan 2025",
|
||||||
|
comments: [
|
||||||
|
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
||||||
|
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Post Title 2",
|
||||||
|
date: "4 July 2022",
|
||||||
|
comments: [
|
||||||
|
{ author: "User 1", date: "1 Jan 2025", content: "This is a comment" },
|
||||||
|
{ author: "User 2", date: "2 Jan 2025", content: "Second comment" },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
fun render_comment(c)
|
||||||
|
<div class="comment">
|
||||||
|
<a>\c.author (\c.date)</a>
|
||||||
|
<p>\c.content</p>
|
||||||
|
<div class="comment-children">
|
||||||
|
\for child in c.children:
|
||||||
|
render_comment(child)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>\title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a>This is regular text</a>
|
||||||
|
\for post in posts:
|
||||||
|
<div class="post">
|
||||||
|
<a>\post.title (\post.date)</a>
|
||||||
|
\for comment in post.comments:
|
||||||
|
render_comment(comment)
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
+119
-67
@@ -43,6 +43,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
ScopeType type;
|
ScopeType type;
|
||||||
int sym_base;
|
int sym_base;
|
||||||
|
int max_vars;
|
||||||
FunctionCall* calls;
|
FunctionCall* calls;
|
||||||
} Scope;
|
} Scope;
|
||||||
|
|
||||||
@@ -212,29 +213,48 @@ int count_nodes(Node *head)
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_symbol_in_local_scope(Assembler *a, String name)
|
Scope *parent_scope(Assembler *a)
|
||||||
{
|
|
||||||
for (int i = a->num_syms-1; i >= a->scopes[a->num_scopes-1].sym_base; i--)
|
|
||||||
if (streq(a->syms[i].name, name))
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int find_symbol_in_function(Assembler *a, String name)
|
|
||||||
{
|
{
|
||||||
assert(a->num_scopes > 0);
|
assert(a->num_scopes > 0);
|
||||||
|
|
||||||
// Find the index of the parent function scope or the global scope
|
|
||||||
int parent = a->num_scopes-1;
|
int parent = a->num_scopes-1;
|
||||||
while (parent > 1 && a->scopes[parent].type != SCOPE_FUNC)
|
while (a->scopes[parent].type != SCOPE_FUNC
|
||||||
|
&& a->scopes[parent].type != SCOPE_GLOBAL)
|
||||||
parent--;
|
parent--;
|
||||||
|
|
||||||
for (int i = a->num_syms-1; i >= a->scopes[parent].sym_base; i--)
|
Scope *scope = &a->scopes[parent];
|
||||||
if (streq(a->syms[i].name, name))
|
|
||||||
return i;
|
|
||||||
|
|
||||||
return -1;
|
assert(scope->type == SCOPE_GLOBAL
|
||||||
|
|| scope->type == SCOPE_FUNC);
|
||||||
|
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol *find_symbol_in_local_scope(Assembler *a, String name)
|
||||||
|
{
|
||||||
|
for (int i = a->num_syms-1; i >= a->scopes[a->num_scopes-1].sym_base; i--)
|
||||||
|
if (streq(a->syms[i].name, name))
|
||||||
|
return &a->syms[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol *find_symbol_in_function(Assembler *a, String name)
|
||||||
|
{
|
||||||
|
Scope *scope = parent_scope(a);
|
||||||
|
for (int i = a->num_syms-1; i >= scope->sym_base; i--)
|
||||||
|
if (streq(a->syms[i].name, name))
|
||||||
|
return &a->syms[i];
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_local_vars(Assembler *a)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
Scope *scope = parent_scope(a);
|
||||||
|
for (int i = scope->sym_base; i < a->num_syms; i++)
|
||||||
|
if (a->syms[i].type == SYMBOL_VAR)
|
||||||
|
n++;
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int declare_variable(Assembler *a, String name)
|
int declare_variable(Assembler *a, String name)
|
||||||
@@ -244,14 +264,21 @@ int declare_variable(Assembler *a, String name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_symbol_in_local_scope(a, name) >= 0) {
|
if (find_symbol_in_local_scope(a, name)) {
|
||||||
assembler_report(a, "Symbol '%.*s' already declared in this scope",
|
assembler_report(a, "Symbol '%.*s' already declared in this scope",
|
||||||
name.len, name.ptr);
|
name.len, name.ptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
a->syms[a->num_syms] = (Symbol) { SYMBOL_VAR, name, -1 };
|
int off = count_local_vars(a);
|
||||||
return a->num_syms++;
|
a->syms[a->num_syms++] = (Symbol) { SYMBOL_VAR, name, off };
|
||||||
|
|
||||||
|
Scope *scope = parent_scope(a);
|
||||||
|
|
||||||
|
if (scope->max_vars < off + 1)
|
||||||
|
scope->max_vars = off + 1;
|
||||||
|
|
||||||
|
return off;
|
||||||
}
|
}
|
||||||
|
|
||||||
int declare_function(Assembler *a, String name, int off)
|
int declare_function(Assembler *a, String name, int off)
|
||||||
@@ -261,14 +288,13 @@ int declare_function(Assembler *a, String name, int off)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_symbol_in_local_scope(a, name) >= 0) {
|
if (find_symbol_in_local_scope(a, name)) {
|
||||||
assembler_report(a, "Symbol '%.*s' already declared in this scope",
|
assembler_report(a, "Symbol '%.*s' already declared in this scope", name.len, name.ptr);
|
||||||
name.len, name.ptr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
a->syms[a->num_syms] = (Symbol) { SYMBOL_FUNC, name, off };
|
a->syms[a->num_syms++] = (Symbol) { SYMBOL_FUNC, name, off };
|
||||||
return a->num_syms++;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -352,6 +378,7 @@ int push_scope(Assembler *a, ScopeType type)
|
|||||||
Scope *scope = &a->scopes[a->num_scopes++];
|
Scope *scope = &a->scopes[a->num_scopes++];
|
||||||
scope->type = type;
|
scope->type = type;
|
||||||
scope->sym_base = a->num_syms;
|
scope->sym_base = a->num_syms;
|
||||||
|
scope->max_vars = 0;
|
||||||
scope->calls = NULL;
|
scope->calls = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -364,15 +391,14 @@ int pop_scope(Assembler *a)
|
|||||||
FunctionCall **prev = &scope->calls;
|
FunctionCall **prev = &scope->calls;
|
||||||
while (call) {
|
while (call) {
|
||||||
|
|
||||||
int idx = find_symbol_in_local_scope(a, call->name);
|
Symbol *sym = find_symbol_in_local_scope(a, call->name);
|
||||||
|
|
||||||
if (idx == -1) {
|
if (sym == NULL) {
|
||||||
prev = &call->next;
|
prev = &call->next;
|
||||||
call = call->next;
|
call = call->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *sym = &a->syms[idx];
|
|
||||||
if (sym->type != SYMBOL_FUNC) {
|
if (sym->type != SYMBOL_FUNC) {
|
||||||
assembler_report(a, "Symbol '%.*s' is not a function", call->name.len, call->name.ptr);
|
assembler_report(a, "Symbol '%.*s' is not a function", call->name.len, call->name.ptr);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -405,8 +431,6 @@ int pop_scope(Assembler *a)
|
|||||||
|
|
||||||
void assemble_node(Assembler *a, Node *node)
|
void assemble_node(Assembler *a, Node *node)
|
||||||
{
|
{
|
||||||
printf("Compiling [%.*s]\n", node->text.len, node->text.ptr);
|
|
||||||
|
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
||||||
case NODE_FUNC_DECL:
|
case NODE_FUNC_DECL:
|
||||||
@@ -420,6 +444,9 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
ret = push_scope(a, SCOPE_FUNC);
|
ret = push_scope(a, SCOPE_FUNC);
|
||||||
if (ret < 0) return;
|
if (ret < 0) return;
|
||||||
|
|
||||||
|
append_u8(&a->out, OPCODE_VARS);
|
||||||
|
int p = append_u32(&a->out, 0);
|
||||||
|
|
||||||
Node *args[32];
|
Node *args[32];
|
||||||
int arg_count = 0;
|
int arg_count = 0;
|
||||||
Node *arg = node->func_args;
|
Node *arg = node->func_args;
|
||||||
@@ -434,11 +461,11 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
|
|
||||||
for (int i = arg_count-1; i >= 0; i--) {
|
for (int i = arg_count-1; i >= 0; i--) {
|
||||||
|
|
||||||
int idx = declare_variable(a, args[i]->sval);
|
int off = declare_variable(a, args[i]->sval);
|
||||||
if (idx < 0) return;
|
if (off < 0) return;
|
||||||
|
|
||||||
append_u8(&a->out, OPCODE_SETV);
|
append_u8(&a->out, OPCODE_SETV);
|
||||||
append_u8(&a->out, idx); // TODO: make this relative to the frame
|
append_u8(&a->out, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_expr(node->func_body)) {
|
if (is_expr(node->func_body)) {
|
||||||
@@ -450,6 +477,8 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
append_u8(&a->out, OPCODE_RET);
|
append_u8(&a->out, OPCODE_RET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
patch_u32(&a->out, p, a->scopes[a->num_scopes-1].max_vars);
|
||||||
|
|
||||||
ret = pop_scope(a);
|
ret = pop_scope(a);
|
||||||
if (ret < 0) return;
|
if (ret < 0) return;
|
||||||
|
|
||||||
@@ -493,14 +522,16 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
|
|
||||||
case NODE_VAR_DECL:
|
case NODE_VAR_DECL:
|
||||||
{
|
{
|
||||||
int idx = declare_variable(a, node->var_name);
|
int off = declare_variable(a, node->var_name);
|
||||||
if (idx < 0) return;
|
if (off < 0) return;
|
||||||
|
|
||||||
if (node->var_value) {
|
if (node->var_value)
|
||||||
assemble_node(a, node->var_value);
|
assemble_node(a, node->var_value);
|
||||||
|
else
|
||||||
|
append_u8(&a->out, OPCODE_PUSHN);
|
||||||
|
|
||||||
append_u8(&a->out, OPCODE_SETV);
|
append_u8(&a->out, OPCODE_SETV);
|
||||||
append_u8(&a->out, idx);
|
append_u8(&a->out, off);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -726,13 +757,17 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
case NODE_VALUE_VAR:
|
case NODE_VALUE_VAR:
|
||||||
{
|
{
|
||||||
String name = node->sval;
|
String name = node->sval;
|
||||||
int idx = find_symbol_in_function(a, name);
|
Symbol *sym = find_symbol_in_function(a, name);
|
||||||
if (idx < 0) {
|
if (sym == NULL) {
|
||||||
assembler_report(a, "Reference to undefined variable '%.*s'", name.len, name.ptr);
|
assembler_report(a, "Reference to undefined variable '%.*s'", name.len, name.ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (sym->type != SYMBOL_VAR) {
|
||||||
|
assembler_report(a, "Symbol '%.*s' is not a variable", sym->name.len, sym->name.ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
append_u8(&a->out, OPCODE_PUSHV);
|
append_u8(&a->out, OPCODE_PUSHV);
|
||||||
append_u8(&a->out, idx); // TODO: make this relative to the frame
|
append_u8(&a->out, sym->off);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -794,20 +829,20 @@ void assemble_node(Assembler *a, Node *node)
|
|||||||
|
|
||||||
String name = dst->sval;
|
String name = dst->sval;
|
||||||
|
|
||||||
int idx = find_symbol_in_function(a, name);
|
Symbol *sym = find_symbol_in_function(a, name);
|
||||||
if (idx < 0) {
|
if (sym == NULL) {
|
||||||
assembler_report(a, "Undeclared variable '%.*s'", name.len, name.ptr);
|
assembler_report(a, "Undeclared variable '%.*s'", name.len, name.ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a->syms[idx].type != SYMBOL_VAR) {
|
if (sym->type != SYMBOL_VAR) {
|
||||||
assembler_report(a, "Symbol '%.*s' can't be assigned to", name.len, name.ptr);
|
assembler_report(a, "Symbol '%.*s' can't be assigned to", name.len, name.ptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assemble_node(a, src);
|
assemble_node(a, src);
|
||||||
append_u8(&a->out, OPCODE_SETV);
|
append_u8(&a->out, OPCODE_SETV);
|
||||||
append_u8(&a->out, idx); // TODO: this index should be relative to the frame
|
append_u8(&a->out, sym->off);
|
||||||
|
|
||||||
} else if (dst->type == NODE_SELECT) {
|
} else if (dst->type == NODE_SELECT) {
|
||||||
|
|
||||||
@@ -839,34 +874,31 @@ AssembleResult assemble(Node *root, Arena *arena, char *errbuf, int errmax)
|
|||||||
{
|
{
|
||||||
Assembler a = {0, .a=arena, .errbuf=errbuf, .errmax=errmax, .errlen=0};
|
Assembler a = {0, .a=arena, .errbuf=errbuf, .errmax=errmax, .errlen=0};
|
||||||
|
|
||||||
append_u32(&a.out, 0xFEEDBEEF); // magic
|
|
||||||
int p1 = append_u32(&a.out, 0); // code size
|
|
||||||
int p2 = append_u32(&a.out, 0); // data size
|
|
||||||
|
|
||||||
int ret = push_scope(&a, SCOPE_GLOBAL);
|
int ret = push_scope(&a, SCOPE_GLOBAL);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
return (AssembleResult) { (Program) {0}, a.errlen };
|
return (AssembleResult) { (Program) {0}, a.errlen };
|
||||||
}
|
|
||||||
|
append_u8(&a.out, OPCODE_VARS);
|
||||||
|
int p = append_u32(&a.out, 0);
|
||||||
|
|
||||||
assemble_node(&a, root);
|
assemble_node(&a, root);
|
||||||
append_u8(&a.out, OPCODE_NOPE);
|
append_u8(&a.out, OPCODE_EXIT);
|
||||||
|
|
||||||
|
patch_u32(&a.out, p, a.scopes[a.num_scopes-1].max_vars);
|
||||||
|
|
||||||
ret = pop_scope(&a);
|
ret = pop_scope(&a);
|
||||||
if (ret < 0) {
|
if (ret < 0)
|
||||||
return (AssembleResult) { (Program) {0}, a.errlen };
|
return (AssembleResult) { (Program) {0}, a.errlen };
|
||||||
}
|
|
||||||
|
|
||||||
patch_u32(&a.out, p1, a.out.len - 3 * sizeof(uint32_t));
|
OutputBuffer out = {0};
|
||||||
patch_u32(&a.out, p2, a.strings_len);
|
append_u32(&out, 0xFEEDBEEF); // magic
|
||||||
|
append_u32(&out, a.out.len); // code size
|
||||||
|
append_u32(&out, a.strings_len); // data size
|
||||||
|
append_mem(&out, a.out.ptr, a.out.len);
|
||||||
|
append_mem(&out, a.strings, a.strings_len);
|
||||||
|
|
||||||
append_mem(&a.out, a.strings, a.strings_len);
|
free(a.out.ptr);
|
||||||
|
return (AssembleResult) { (Program) { out.ptr, out.len }, a.errlen };
|
||||||
Program p = {
|
|
||||||
a.out.ptr,
|
|
||||||
a.out.len,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (AssembleResult) { p, a.errlen };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_program(Program p)
|
void print_program(Program p)
|
||||||
@@ -899,7 +931,7 @@ void print_program(Program p)
|
|||||||
|
|
||||||
while (cur < code_size + 3 * sizeof(uint32_t)) {
|
while (cur < code_size + 3 * sizeof(uint32_t)) {
|
||||||
|
|
||||||
printf("%d: ", cur - 3 * sizeof(uint32_t));
|
printf("%" LLU ": ", cur - 3 * sizeof(uint32_t));
|
||||||
|
|
||||||
switch (((uint8_t*) p.ptr)[cur++]) {
|
switch (((uint8_t*) p.ptr)[cur++]) {
|
||||||
|
|
||||||
@@ -907,6 +939,10 @@ void print_program(Program p)
|
|||||||
printf("NOPE");
|
printf("NOPE");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_EXIT:
|
||||||
|
printf("EXIT");
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_PUSHI:
|
case OPCODE_PUSHI:
|
||||||
{
|
{
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
@@ -971,6 +1007,12 @@ void print_program(Program p)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_PUSHN:
|
||||||
|
{
|
||||||
|
printf("PUSHN");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_POP:
|
case OPCODE_POP:
|
||||||
printf("POP");
|
printf("POP");
|
||||||
break;
|
break;
|
||||||
@@ -1051,14 +1093,24 @@ void print_program(Program p)
|
|||||||
memcpy(&num, p.ptr + cur, sizeof(uint8_t));
|
memcpy(&num, p.ptr + cur, sizeof(uint8_t));
|
||||||
cur += sizeof(uint8_t);
|
cur += sizeof(uint8_t);
|
||||||
|
|
||||||
uint8_t off;
|
uint32_t off;
|
||||||
memcpy(&off, p.ptr + cur, sizeof(uint8_t));
|
memcpy(&off, p.ptr + cur, sizeof(uint32_t));
|
||||||
cur += sizeof(uint8_t);
|
cur += sizeof(uint32_t);
|
||||||
|
|
||||||
printf("CALL %u %u", num, off);
|
printf("CALL %u %u", num, off);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OPCODE_VARS:
|
||||||
|
{
|
||||||
|
uint32_t num;
|
||||||
|
memcpy(&num, p.ptr + cur, sizeof(uint32_t));
|
||||||
|
cur += sizeof(uint32_t);
|
||||||
|
|
||||||
|
printf("VARS %u", num);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case OPCODE_RET:
|
case OPCODE_RET:
|
||||||
printf("RET");
|
printf("RET");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPCODE_NOPE = 0x00,
|
OPCODE_NOPE = 0x00,
|
||||||
|
OPCODE_EXIT = 0x23,
|
||||||
OPCODE_PUSHI = 0x01,
|
OPCODE_PUSHI = 0x01,
|
||||||
OPCODE_PUSHF = 0x02,
|
OPCODE_PUSHF = 0x02,
|
||||||
OPCODE_PUSHS = 0x03,
|
OPCODE_PUSHS = 0x03,
|
||||||
@@ -27,6 +28,7 @@ enum {
|
|||||||
OPCODE_JUMP = 0x13,
|
OPCODE_JUMP = 0x13,
|
||||||
OPCODE_JIFP = 0x14,
|
OPCODE_JIFP = 0x14,
|
||||||
OPCODE_CALL = 0x15,
|
OPCODE_CALL = 0x15,
|
||||||
|
OPCODE_VARS = 0x22,
|
||||||
OPCODE_RET = 0x16,
|
OPCODE_RET = 0x16,
|
||||||
OPCODE_APPEND = 0x17,
|
OPCODE_APPEND = 0x17,
|
||||||
OPCODE_INSERT1 = 0x18,
|
OPCODE_INSERT1 = 0x18,
|
||||||
|
|||||||
+507
-156
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
#include "assemble.h"
|
#include "assemble.h"
|
||||||
|
|
||||||
void eval(Program program);
|
int eval(Program p, Arena *a, char *errbuf, int errmax);
|
||||||
|
|
||||||
#endif // WL_EVAL_INCLUDED
|
#endif // WL_EVAL_INCLUDED
|
||||||
|
|||||||
+6
-1
@@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
#include "eval.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "assemble.h"
|
#include "assemble.h"
|
||||||
|
|
||||||
@@ -35,7 +36,11 @@ int main(void)
|
|||||||
|
|
||||||
print_program(assemble_result.program);
|
print_program(assemble_result.program);
|
||||||
|
|
||||||
eval(assemble_result.program);
|
ret = eval(assemble_result.program, &a, err, COUNT(err));
|
||||||
|
if (ret < 0) {
|
||||||
|
printf("%s\n", err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
free(src.ptr);
|
free(src.ptr);
|
||||||
free(mem);
|
free(mem);
|
||||||
|
|||||||
+2
-2
@@ -361,7 +361,6 @@ Token next_token(Parser *p)
|
|||||||
return (Token) { .type=TOKEN_VALUE_STR, .sval=(String) { .ptr=buf, .len=len } };
|
return (Token) { .type=TOKEN_VALUE_STR, .sval=(String) { .ptr=buf, .len=len } };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consume_str(&p->s, S("="))) return (Token) { .type=TOKEN_OPER_ASS };
|
|
||||||
if (consume_str(&p->s, S("=="))) return (Token) { .type=TOKEN_OPER_EQL };
|
if (consume_str(&p->s, S("=="))) return (Token) { .type=TOKEN_OPER_EQL };
|
||||||
if (consume_str(&p->s, S("!="))) return (Token) { .type=TOKEN_OPER_NQL };
|
if (consume_str(&p->s, S("!="))) return (Token) { .type=TOKEN_OPER_NQL };
|
||||||
if (consume_str(&p->s, S("<"))) return (Token) { .type=TOKEN_OPER_LSS };
|
if (consume_str(&p->s, S("<"))) return (Token) { .type=TOKEN_OPER_LSS };
|
||||||
@@ -371,6 +370,7 @@ Token next_token(Parser *p)
|
|||||||
if (consume_str(&p->s, S("*"))) return (Token) { .type=TOKEN_OPER_MUL };
|
if (consume_str(&p->s, S("*"))) return (Token) { .type=TOKEN_OPER_MUL };
|
||||||
if (consume_str(&p->s, S("/"))) return (Token) { .type=TOKEN_OPER_DIV };
|
if (consume_str(&p->s, S("/"))) return (Token) { .type=TOKEN_OPER_DIV };
|
||||||
if (consume_str(&p->s, S("%"))) return (Token) { .type=TOKEN_OPER_MOD };
|
if (consume_str(&p->s, S("%"))) return (Token) { .type=TOKEN_OPER_MOD };
|
||||||
|
if (consume_str(&p->s, S("="))) return (Token) { .type=TOKEN_OPER_ASS };
|
||||||
|
|
||||||
if (consume_str(&p->s, S("("))) return (Token) { .type=TOKEN_PAREN_OPEN };
|
if (consume_str(&p->s, S("("))) return (Token) { .type=TOKEN_PAREN_OPEN };
|
||||||
if (consume_str(&p->s, S(")"))) return (Token) { .type=TOKEN_PAREN_CLOSE };
|
if (consume_str(&p->s, S(")"))) return (Token) { .type=TOKEN_PAREN_CLOSE };
|
||||||
@@ -1737,7 +1737,7 @@ void print_node(Node *node)
|
|||||||
printf(" = ");
|
printf(" = ");
|
||||||
print_node(node->var_value);
|
print_node(node->var_value);
|
||||||
}
|
}
|
||||||
printf(";");
|
//printf(";");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user