Compare commits
2 Commits
9ca893dff5
...
d8f1af99a6
Author | SHA1 | Date |
---|---|---|
bog | d8f1af99a6 | |
bog | 299c095af4 |
|
@ -48,6 +48,8 @@ executable(
|
||||||
'src/compiler.c',
|
'src/compiler.c',
|
||||||
'src/cstatic.c',
|
'src/cstatic.c',
|
||||||
'src/vm.c',
|
'src/vm.c',
|
||||||
|
|
||||||
|
'src/symtable.c',
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
m_dep
|
m_dep
|
||||||
|
|
152
src/compiler.c
152
src/compiler.c
|
@ -4,11 +4,18 @@
|
||||||
void compiler_init(compiler* self)
|
void compiler_init(compiler* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
self->sym = malloc(sizeof(symtable));
|
||||||
|
symtable_init(self->sym);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_free(compiler* self)
|
void compiler_free(compiler* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
symtable_free(self->sym);
|
||||||
|
free(self->sym);
|
||||||
|
self->sym = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_node(compiler* self, node* root, program* prog)
|
void compile_node(compiler* self, node* root, program* prog)
|
||||||
|
@ -22,13 +29,54 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
compile_children(self, root, prog);
|
compile_children(self, root, prog);
|
||||||
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
||||||
}
|
}
|
||||||
|
// Variables stuff
|
||||||
|
else if (root->type == NODE_VARDECL)
|
||||||
|
{
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
|
||||||
|
type* ty = cstatic_resolve_new(&cs,
|
||||||
|
self->sym,
|
||||||
|
root->children.data[1]);
|
||||||
|
|
||||||
|
size_t id = symtable_declare(
|
||||||
|
self->sym,
|
||||||
|
root->children.data[0]->value,
|
||||||
|
ty
|
||||||
|
);
|
||||||
|
|
||||||
|
compile_node(self, root->children.data[1], prog);
|
||||||
|
program_add_instr(prog, OP_STORE, id);
|
||||||
|
|
||||||
|
type_free(ty);
|
||||||
|
free(ty);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_IDENT)
|
||||||
|
{
|
||||||
|
symentry* entry = symtable_find(self->sym, root->value);
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E(%d): variable '%s' not declared.\n",
|
||||||
|
root->lineno,
|
||||||
|
root->value);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
program_add_instr(prog, OP_LOAD, entry->id);
|
||||||
|
}
|
||||||
else if (root->type == NODE_MUL)
|
else if (root->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
cstatic cs;
|
cstatic cs;
|
||||||
cstatic_init(&cs);
|
cstatic_init(&cs);
|
||||||
|
|
||||||
int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]);
|
int lhs = cstatic_resolve_base_type(&cs,
|
||||||
int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]);
|
self->sym,
|
||||||
|
root->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve_base_type(&cs, self->sym,
|
||||||
|
root->children.data[1]);
|
||||||
|
|
||||||
cstatic_free(&cs);
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
@ -71,8 +119,10 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
cstatic cs;
|
cstatic cs;
|
||||||
cstatic_init(&cs);
|
cstatic_init(&cs);
|
||||||
|
|
||||||
int lhs = cstatic_resolve_base_type(&cs, root->children.data[0]);
|
int lhs = cstatic_resolve_base_type(&cs,
|
||||||
int rhs = cstatic_resolve_base_type(&cs, root->children.data[1]);
|
self->sym, root->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve_base_type(&cs,
|
||||||
|
self->sym, root->children.data[1]);
|
||||||
|
|
||||||
cstatic_free(&cs);
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
@ -158,6 +208,98 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
compile_children(self, root, prog);
|
compile_children(self, root, prog);
|
||||||
program_add_instr(prog, OP_ASSERT, NO_PARAM);
|
program_add_instr(prog, OP_ASSERT, NO_PARAM);
|
||||||
}
|
}
|
||||||
|
else if (root->type == NODE_LT)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
int base_type = cstatic_resolve_base_type(&cs,
|
||||||
|
self->sym,
|
||||||
|
root->children.data[0]);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (base_type == TY_INTEGER)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_ILT, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (base_type == TY_FLOAT)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_FLT, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_LE)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
int base_type = cstatic_resolve_base_type(&cs,
|
||||||
|
self->sym,
|
||||||
|
root->children.data[0]);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (base_type == TY_INTEGER)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_ILE, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (base_type == TY_FLOAT)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_FLE, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_GT)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
int base_type = cstatic_resolve_base_type(&cs,
|
||||||
|
self->sym,
|
||||||
|
root->children.data[0]);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (base_type == TY_INTEGER)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_IGT, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (base_type == TY_FLOAT)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_FGT, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (root->type == NODE_GE)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
int base_type = cstatic_resolve_base_type(&cs,
|
||||||
|
self->sym,
|
||||||
|
root->children.data[0]);
|
||||||
|
cstatic_free(&cs);
|
||||||
|
|
||||||
|
if (base_type == TY_INTEGER)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_IGE, NO_PARAM);
|
||||||
|
}
|
||||||
|
else if (base_type == TY_FLOAT)
|
||||||
|
{
|
||||||
|
program_add_instr(prog, OP_FGE, NO_PARAM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (root->type == NODE_UADD)
|
else if (root->type == NODE_UADD)
|
||||||
{
|
{
|
||||||
compile_number(self, root, prog, OP_IUADD, OP_FUADD);
|
compile_number(self, root, prog, OP_IUADD, OP_FUADD);
|
||||||
|
@ -304,7 +446,7 @@ void compile_number(compiler* self, node* root, program* prog,
|
||||||
cstatic cs;
|
cstatic cs;
|
||||||
cstatic_init(&cs);
|
cstatic_init(&cs);
|
||||||
|
|
||||||
int ty = cstatic_resolve_base_type(&cs, root);
|
int ty = cstatic_resolve_base_type(&cs, self->sym, root);
|
||||||
|
|
||||||
switch (ty)
|
switch (ty)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "symtable.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int _unused;
|
symtable* sym;
|
||||||
|
|
||||||
} compiler;
|
} compiler;
|
||||||
|
|
||||||
void compiler_init(compiler* self);
|
void compiler_init(compiler* self);
|
||||||
|
|
163
src/cstatic.c
163
src/cstatic.c
|
@ -19,10 +19,10 @@ type* cstatic_new_type(cstatic* self, int base_type)
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_resolve_base_type(cstatic* self, node* ast)
|
int cstatic_resolve_base_type(cstatic* self, symtable* sym, node* ast)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
type* ty = cstatic_resolve_new(self, ast);
|
type* ty = cstatic_resolve_new(self, sym, ast);
|
||||||
int res = ty->base_type;
|
int res = ty->base_type;
|
||||||
type_free(ty);
|
type_free(ty);
|
||||||
free(ty);
|
free(ty);
|
||||||
|
@ -30,27 +30,48 @@ int cstatic_resolve_base_type(cstatic* self, node* ast)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
type* cstatic_resolve_new(cstatic* self, node* ast)
|
type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
|
||||||
|
if (ast->type == NODE_IDENT)
|
||||||
|
{
|
||||||
|
symentry* entry = symtable_find(sym,
|
||||||
|
ast->value);
|
||||||
|
type* ty = type_new_clone(entry->ty);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_VARDECL)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_resolve_new(self,
|
||||||
|
sym,
|
||||||
|
ast->children.data[1]);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
||||||
{
|
{
|
||||||
type_free(rhs); free(rhs);
|
type_free(rhs); free(rhs);
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type_free(rhs); free(rhs);
|
||||||
|
type_free(lhs); free(lhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
int lhs = cstatic_resolve_base_type(self, sym,
|
||||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
ast->children.data[0]);
|
||||||
|
int rhs = cstatic_resolve_base_type(self, sym,
|
||||||
|
ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs == TY_STRING || rhs == TY_STRING)
|
if (lhs == TY_STRING || rhs == TY_STRING)
|
||||||
{
|
{
|
||||||
|
@ -60,8 +81,8 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
|
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs->base_type == TY_INTEGER
|
if (lhs->base_type == TY_INTEGER
|
||||||
&& rhs->base_type == TY_ARRAY)
|
&& rhs->base_type == TY_ARRAY)
|
||||||
|
@ -104,7 +125,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
iter = iter->children.data[0];
|
iter = iter->children.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return cstatic_resolve_new(self, iter);
|
return cstatic_resolve_new(self, sym, iter);
|
||||||
}
|
}
|
||||||
else if (ast->type == NODE_INTEGER)
|
else if (ast->type == NODE_INTEGER)
|
||||||
{
|
{
|
||||||
|
@ -117,7 +138,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
|
|
||||||
else if (ast->type == NODE_ADD)
|
else if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
return cstatic_resolve_new(self, ast->children.data[0]);
|
return cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ast->type == NODE_STRING)
|
else if (ast->type == NODE_STRING)
|
||||||
|
@ -133,7 +154,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
else if (ast->type == NODE_ARRAY)
|
else if (ast->type == NODE_ARRAY)
|
||||||
{
|
{
|
||||||
assert(ast->children.size > 0);
|
assert(ast->children.size > 0);
|
||||||
type* child = cstatic_resolve_new(self, ast->children.data[0]);
|
type* child = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
|
|
||||||
type* ty = malloc(sizeof(type));
|
type* ty = malloc(sizeof(type));
|
||||||
type_init_array(ty, child);
|
type_init_array(ty, child);
|
||||||
|
@ -145,8 +166,13 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ast->type == NODE_BOOLEAN
|
else if (ast->type == NODE_BOOLEAN
|
||||||
|
|| ast->type == NODE_LT
|
||||||
|
|| ast->type == NODE_LE
|
||||||
|
|| ast->type == NODE_GT
|
||||||
|
|| ast->type == NODE_GE
|
||||||
|| ast->type == NODE_EQ
|
|| ast->type == NODE_EQ
|
||||||
|| ast->type == NODE_NE)
|
|| ast->type == NODE_NE)
|
||||||
|
|
||||||
{
|
{
|
||||||
return cstatic_new_type(self, TY_BOOLEAN);
|
return cstatic_new_type(self, TY_BOOLEAN);
|
||||||
}
|
}
|
||||||
|
@ -154,7 +180,8 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
{
|
{
|
||||||
for (size_t i=0; i<ast->children.size; i++)
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
type* ty = cstatic_resolve_new(self, ast->children.data[i]);
|
type* ty = cstatic_resolve_new(self, sym,
|
||||||
|
ast->children.data[i]);
|
||||||
|
|
||||||
if (ty != NULL)
|
if (ty != NULL)
|
||||||
{
|
{
|
||||||
|
@ -166,7 +193,7 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
@ -175,6 +202,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
for (size_t i=0; i<ast->children.size; i++)
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
int status = cstatic_check(self, ast->children.data[i],
|
int status = cstatic_check(self, ast->children.data[i],
|
||||||
|
sym,
|
||||||
msg, size);
|
msg, size);
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
|
@ -214,6 +242,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
int status = cstatic_check_type_base(
|
int status = cstatic_check_type_base(
|
||||||
self,
|
self,
|
||||||
ast->children.data[1]->children.data[i],
|
ast->children.data[1]->children.data[i],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
TY_INTEGER,
|
TY_INTEGER,
|
||||||
|
@ -231,13 +260,14 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
else if (ast->type == NODE_ARRAY)
|
else if (ast->type == NODE_ARRAY)
|
||||||
{
|
{
|
||||||
assert(ast->children.size > 0);
|
assert(ast->children.size > 0);
|
||||||
type* ty = cstatic_resolve_new(self, ast->children.data[0]);
|
type* ty = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
|
|
||||||
for (size_t i=1; i<ast->children.size; i++)
|
for (size_t i=1; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
int status = cstatic_check_type(
|
int status = cstatic_check_type(
|
||||||
self,
|
self,
|
||||||
ast->children.data[i],
|
ast->children.data[i],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
ty,
|
ty,
|
||||||
|
@ -258,11 +288,37 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vars Operations
|
||||||
|
if (ast->type == NODE_IDENT)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_VARDECL)
|
||||||
|
{
|
||||||
|
char const* name = ast->children.data[0]->value;
|
||||||
|
|
||||||
|
if (symtable_find(sym, name))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "E(%d): '%s' is already defined.\n",
|
||||||
|
ast->lineno,
|
||||||
|
name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
type* ty = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
assert(ty);
|
||||||
|
symtable_declare(sym, name, ty);
|
||||||
|
type_free(ty);
|
||||||
|
free(ty);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Types Operations
|
// Types Operations
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
||||||
{
|
{
|
||||||
|
@ -277,8 +333,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
if (lhs->base_type == TY_TYPE && rhs->base_type == TY_TYPE)
|
||||||
{
|
{
|
||||||
|
@ -293,8 +349,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
// Array Operations
|
// Array Operations
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if (lhs->base_type == TY_ARRAY
|
if (lhs->base_type == TY_ARRAY
|
||||||
&& type_equals(lhs, rhs))
|
&& type_equals(lhs, rhs))
|
||||||
|
@ -310,8 +366,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
type* lhs = cstatic_resolve_new(self, ast->children.data[0]);
|
type* lhs = cstatic_resolve_new(self, sym, ast->children.data[0]);
|
||||||
type* rhs = cstatic_resolve_new(self, ast->children.data[1]);
|
type* rhs = cstatic_resolve_new(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if ( (lhs->base_type == TY_ARRAY && rhs->base_type == TY_INTEGER)
|
if ( (lhs->base_type == TY_ARRAY && rhs->base_type == TY_INTEGER)
|
||||||
|| (lhs->base_type == TY_INTEGER && rhs->base_type == TY_ARRAY))
|
|| (lhs->base_type == TY_INTEGER && rhs->base_type == TY_ARRAY))
|
||||||
|
@ -328,8 +384,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
// String Operations
|
// String Operations
|
||||||
if (ast->type == NODE_ADD)
|
if (ast->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
int lhs = cstatic_resolve_base_type(self, sym, ast->children.data[0]);
|
||||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
int rhs = cstatic_resolve_base_type(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
|
|
||||||
if (lhs == rhs && lhs == TY_STRING)
|
if (lhs == rhs && lhs == TY_STRING)
|
||||||
|
@ -340,8 +396,8 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
if (ast->type == NODE_MUL)
|
if (ast->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
int lhs = cstatic_resolve_base_type(self, ast->children.data[0]);
|
int lhs = cstatic_resolve_base_type(self, sym, ast->children.data[0]);
|
||||||
int rhs = cstatic_resolve_base_type(self, ast->children.data[1]);
|
int rhs = cstatic_resolve_base_type(self, sym, ast->children.data[1]);
|
||||||
|
|
||||||
if ((lhs == TY_STRING && rhs == TY_INTEGER)
|
if ((lhs == TY_STRING && rhs == TY_INTEGER)
|
||||||
|| (lhs == TY_INTEGER && rhs == TY_STRING))
|
|| (lhs == TY_INTEGER && rhs == TY_STRING))
|
||||||
|
@ -357,6 +413,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
int status = cstatic_check_same_type(self,
|
int status = cstatic_check_same_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
ast->children.data[1],
|
ast->children.data[1],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
|
@ -372,6 +429,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
{
|
{
|
||||||
int status = cstatic_check_type_base(self,
|
int status = cstatic_check_type_base(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
TY_BOOLEAN,
|
TY_BOOLEAN,
|
||||||
|
@ -390,6 +448,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
int status = cstatic_check_same_type(self,
|
int status = cstatic_check_same_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
ast->children.data[1],
|
ast->children.data[1],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
|
@ -400,6 +459,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
status = cstatic_check_type_base(self,
|
status = cstatic_check_type_base(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
TY_BOOLEAN,
|
TY_BOOLEAN,
|
||||||
|
@ -416,6 +476,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
{
|
{
|
||||||
int status = cstatic_check_type_base(self,
|
int status = cstatic_check_type_base(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
TY_INTEGER,
|
TY_INTEGER,
|
||||||
|
@ -438,6 +499,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
int status = cstatic_check_same_type(self,
|
int status = cstatic_check_same_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
ast->children.data[1],
|
ast->children.data[1],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
|
@ -448,6 +510,39 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
status = cstatic_check_type_base(self,
|
status = cstatic_check_type_base(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
|
sym,
|
||||||
|
msg,
|
||||||
|
size,
|
||||||
|
TY_INTEGER,
|
||||||
|
TY_FLOAT,
|
||||||
|
TYPE_END);
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Comparisons
|
||||||
|
else if (ast->type == NODE_LT
|
||||||
|
|| ast->type == NODE_LE
|
||||||
|
|| ast->type == NODE_GT
|
||||||
|
|| ast->type == NODE_GE
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int status = cstatic_check_same_type(self,
|
||||||
|
ast->children.data[0],
|
||||||
|
ast->children.data[1],
|
||||||
|
sym,
|
||||||
|
msg,
|
||||||
|
size);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = cstatic_check_type_base(self,
|
||||||
|
ast->children.data[0],
|
||||||
|
sym,
|
||||||
msg,
|
msg,
|
||||||
size,
|
size,
|
||||||
TY_INTEGER,
|
TY_INTEGER,
|
||||||
|
@ -462,7 +557,7 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check_type(cstatic* self, node* lhs,
|
int cstatic_check_type(cstatic* self, node* lhs, symtable* sym,
|
||||||
char* msg, size_t size, type* types, ...)
|
char* msg, size_t size, type* types, ...)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -474,7 +569,7 @@ int cstatic_check_type(cstatic* self, node* lhs,
|
||||||
va_start(args, types);
|
va_start(args, types);
|
||||||
type* rhs = types;
|
type* rhs = types;
|
||||||
|
|
||||||
type* left = cstatic_resolve_new(self, lhs);
|
type* left = cstatic_resolve_new(self, sym, lhs);
|
||||||
|
|
||||||
type* all_types[TY_TYPE_COUNT];
|
type* all_types[TY_TYPE_COUNT];
|
||||||
|
|
||||||
|
@ -523,7 +618,7 @@ int cstatic_check_type(cstatic* self, node* lhs,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check_type_base(cstatic* self, node* lhs,
|
int cstatic_check_type_base(cstatic* self, node* lhs, symtable* sym,
|
||||||
char* msg, size_t size, int types, ...)
|
char* msg, size_t size, int types, ...)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -535,7 +630,7 @@ int cstatic_check_type_base(cstatic* self, node* lhs,
|
||||||
va_start(args, types);
|
va_start(args, types);
|
||||||
int rhs = types;
|
int rhs = types;
|
||||||
|
|
||||||
int left = cstatic_resolve_base_type(self, lhs);
|
int left = cstatic_resolve_base_type(self, sym, lhs);
|
||||||
|
|
||||||
int all_types[TY_TYPE_COUNT];
|
int all_types[TY_TYPE_COUNT];
|
||||||
memset(all_types, TYPE_END, TY_TYPE_COUNT * sizeof(int));
|
memset(all_types, TYPE_END, TY_TYPE_COUNT * sizeof(int));
|
||||||
|
@ -575,15 +670,15 @@ int cstatic_check_type_base(cstatic* self, node* lhs,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
||||||
char* msg, size_t size)
|
char* msg, size_t size)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(lhs);
|
assert(lhs);
|
||||||
assert(rhs);
|
assert(rhs);
|
||||||
|
|
||||||
type* left = cstatic_resolve_new(self, lhs);
|
type* left = cstatic_resolve_new(self, sym, lhs);
|
||||||
type* right = cstatic_resolve_new(self, rhs);
|
type* right = cstatic_resolve_new(self, sym, rhs);
|
||||||
|
|
||||||
if (!type_equals(left, right))
|
if (!type_equals(left, right))
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "type.h"
|
#include "symtable.h"
|
||||||
|
|
||||||
#define TYPE_END (-1)
|
#define TYPE_END (-1)
|
||||||
|
|
||||||
|
@ -15,18 +15,18 @@ void cstatic_init(cstatic* self);
|
||||||
void cstatic_free(cstatic* self);
|
void cstatic_free(cstatic* self);
|
||||||
|
|
||||||
type* cstatic_new_type(cstatic* self, int base_type);
|
type* cstatic_new_type(cstatic* self, int base_type);
|
||||||
int cstatic_resolve_base_type(cstatic* self, node* ast);
|
int cstatic_resolve_base_type(cstatic* self, symtable* sym, node* ast);
|
||||||
|
|
||||||
type* cstatic_resolve_new(cstatic* self, node* ast);
|
type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast);
|
||||||
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size);
|
int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t size);
|
||||||
|
|
||||||
int cstatic_check_type(cstatic* self, node* lhs,
|
int cstatic_check_type(cstatic* self, node* lhs, symtable* sym,
|
||||||
char* msg, size_t size, type* types, ...);
|
char* msg, size_t size, type* types, ...);
|
||||||
|
|
||||||
int cstatic_check_type_base(cstatic* self, node* lhs,
|
int cstatic_check_type_base(cstatic* self, node* lhs, symtable* sym,
|
||||||
char* msg, size_t size, int types, ...);
|
char* msg, size_t size, int types, ...);
|
||||||
|
|
||||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs, symtable* sym,
|
||||||
char* msg, size_t size);
|
char* msg, size_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,7 @@ INTEGER -?[0-9]+
|
||||||
FLOAT -?[0-9]+\.[0-9]+
|
FLOAT -?[0-9]+\.[0-9]+
|
||||||
STRING \"[^"]*\"
|
STRING \"[^"]*\"
|
||||||
TYPE (int|float|bool|str|array)
|
TYPE (int|float|bool|str|array)
|
||||||
|
IDENT [_A-Za-z][_A-Za-z0-9]*
|
||||||
|
|
||||||
%%
|
%%
|
||||||
{COMMENT} {}
|
{COMMENT} {}
|
||||||
|
@ -25,7 +26,10 @@ TYPE (int|float|bool|str|array)
|
||||||
return TYPE;
|
return TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"let" { return LET; }
|
||||||
"assert" { return ASSERT; }
|
"assert" { return ASSERT; }
|
||||||
|
"<=" { return LE; }
|
||||||
|
">=" { return GE; }
|
||||||
"<" { return LT; }
|
"<" { return LT; }
|
||||||
">" { return GT; }
|
">" { return GT; }
|
||||||
"," { return COMMA; }
|
"," { return COMMA; }
|
||||||
|
@ -45,6 +49,7 @@ TYPE (int|float|bool|str|array)
|
||||||
")" { return CPAR; }
|
")" { return CPAR; }
|
||||||
"[" { return OSQUARE; }
|
"[" { return OSQUARE; }
|
||||||
"]" { return CSQUARE; }
|
"]" { return CSQUARE; }
|
||||||
|
"=" { return ASSIGN; }
|
||||||
|
|
||||||
{BOOLEAN} {
|
{BOOLEAN} {
|
||||||
yylval.str = yytext;
|
yylval.str = yytext;
|
||||||
|
@ -66,6 +71,10 @@ TYPE (int|float|bool|str|array)
|
||||||
return INTEGER;
|
return INTEGER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{IDENT} {
|
||||||
|
yylval.str = yytext;
|
||||||
|
return IDENT;
|
||||||
|
}
|
||||||
|
|
||||||
. {
|
. {
|
||||||
fprintf(stderr, "E(%d): Lexical error near '%s'.\n", line, yytext);
|
fprintf(stderr, "E(%d): Lexical error near '%s'.\n", line, yytext);
|
||||||
|
|
|
@ -28,19 +28,21 @@ int main(int argc, char** argv)
|
||||||
stack_free();
|
stack_free();
|
||||||
|
|
||||||
// Static checking
|
// Static checking
|
||||||
|
symtable sym;
|
||||||
|
symtable_init(&sym);
|
||||||
cstatic cs;
|
cstatic cs;
|
||||||
cstatic_init(&cs);
|
cstatic_init(&cs);
|
||||||
size_t const SZ = 512;
|
size_t const SZ = 512;
|
||||||
char msg[SZ];
|
char msg[SZ];
|
||||||
|
|
||||||
int status = cstatic_check(&cs, ast, msg, SZ);
|
int status = cstatic_check(&cs, ast, &sym, msg, SZ);
|
||||||
|
symtable_free(&sym);
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", msg);
|
fprintf(stderr, "%s\n", msg);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compilation
|
// Compilation
|
||||||
compiler comp;
|
compiler comp;
|
||||||
compiler_init(&comp);
|
compiler_init(&comp);
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
G(NODE_ASSERT), \
|
G(NODE_ASSERT), \
|
||||||
G(NODE_UADD), G(NODE_USUB), G(NODE_ADD), G(NODE_SUB), \
|
G(NODE_UADD), G(NODE_USUB), G(NODE_ADD), G(NODE_SUB), \
|
||||||
G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
||||||
G(NODE_ARRAY), G(NODE_INDEX)
|
G(NODE_ARRAY), G(NODE_INDEX), G(NODE_LT), G(NODE_LE), \
|
||||||
|
G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT)
|
||||||
|
|
||||||
|
|
||||||
#include "mutils.h"
|
#include "mutils.h"
|
||||||
|
|
|
@ -33,7 +33,17 @@
|
||||||
G(OP_ACAT), \
|
G(OP_ACAT), \
|
||||||
G(OP_AMUL), \
|
G(OP_AMUL), \
|
||||||
G(OP_TMUL), \
|
G(OP_TMUL), \
|
||||||
G(OP_TADD)
|
G(OP_TADD), \
|
||||||
|
G(OP_ILT), \
|
||||||
|
G(OP_ILE), \
|
||||||
|
G(OP_IGT), \
|
||||||
|
G(OP_IGE), \
|
||||||
|
G(OP_FLT), \
|
||||||
|
G(OP_FLE), \
|
||||||
|
G(OP_FGT), \
|
||||||
|
G(OP_FGE), \
|
||||||
|
G(OP_STORE), \
|
||||||
|
G(OP_LOAD)
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
OPCODES(GEN_ENUM)
|
OPCODES(GEN_ENUM)
|
||||||
|
|
109
src/parser.y
109
src/parser.y
|
@ -22,21 +22,20 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
%left ASSERT
|
%left ASSERT
|
||||||
%token LT GT
|
%token <str> TYPE BOOLEAN INTEGER FLOAT STRING IDENT
|
||||||
%token <str> TYPE BOOLEAN INTEGER FLOAT STRING
|
|
||||||
%type <n_children> expr exprs prog array builtins
|
%type <n_children> expr exprs prog array builtins
|
||||||
%type <n_children> expr_list type type_list
|
%type <n_children> expr_list type type_list ident
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
|
%left LT GT LE GE
|
||||||
%left AND
|
%left AND
|
||||||
%left OR
|
%left OR
|
||||||
%left ADD
|
%left ADD SUB
|
||||||
%left SUB
|
|
||||||
%left MUL DIV MOD
|
%left MUL DIV MOD
|
||||||
%left POW
|
%left POW
|
||||||
%left NOT
|
%left NOT
|
||||||
%token OPAR CPAR
|
%token OPAR CPAR
|
||||||
%token OSQUARE CSQUARE COMMA
|
%token OSQUARE CSQUARE COMMA
|
||||||
|
%token LET ASSIGN
|
||||||
%type <n_children> expr_unop
|
%type <n_children> expr_unop
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
@ -98,6 +97,25 @@ expr:
|
||||||
stack_push(n);
|
stack_push(n);
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VARIABLES
|
||||||
|
| ident {
|
||||||
|
}
|
||||||
|
|
||||||
|
| LET ident ASSIGN expr {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_VARDECL, "", line);
|
||||||
|
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// EXPRESSIONS
|
// EXPRESSIONS
|
||||||
| array {
|
| array {
|
||||||
|
@ -118,9 +136,49 @@ expr:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
| expr_unop {}
|
|
||||||
|
|
||||||
| expr ADD expr{
|
| expr LT expr {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_LT, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| expr LE expr {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_LE, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| expr GT expr {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_GT, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| expr GE expr {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_GE, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| expr ADD expr {
|
||||||
node *n = malloc(sizeof(node));
|
node *n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_ADD, "", line);
|
node_init(n, NODE_ADD, "", line);
|
||||||
node* rhs = stack_pop();
|
node* rhs = stack_pop();
|
||||||
|
@ -243,6 +301,7 @@ expr:
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| expr_unop {}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -265,8 +324,8 @@ expr_unop:
|
||||||
;
|
;
|
||||||
|
|
||||||
type_list:
|
type_list:
|
||||||
expr { $$ = $1; }
|
type { $$ = $1; }
|
||||||
| type_list COMMA expr { $$ = $1 + $3; }
|
| type_list COMMA type { $$ = $1 + $3; }
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -299,6 +358,36 @@ type:
|
||||||
stack_push(n);
|
stack_push(n);
|
||||||
$$ = 1;
|
$$ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| type ADD type {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_ADD, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
| type MUL type {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_MUL, "", line);
|
||||||
|
node* rhs = stack_pop();
|
||||||
|
node* lhs = stack_pop();
|
||||||
|
node_add_child(n, lhs);
|
||||||
|
node_add_child(n, rhs);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
ident: IDENT {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_IDENT, $1, line);
|
||||||
|
stack_push(n);
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
builtins:
|
builtins:
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#include "symtable.h"
|
||||||
|
|
||||||
|
void symtable_init(symtable* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->id = 0;
|
||||||
|
|
||||||
|
self->entries.size = 0;
|
||||||
|
self->entries.capacity = 1;
|
||||||
|
self->entries.data = malloc(sizeof(symentry*)
|
||||||
|
* self->entries.capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void symtable_free(symtable* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
|
{
|
||||||
|
free(self->entries.data[i]->name);
|
||||||
|
type_free(self->entries.data[i]->ty);
|
||||||
|
free(self->entries.data[i]->ty);
|
||||||
|
free(self->entries.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->entries.data);
|
||||||
|
|
||||||
|
self->entries.size = 0;
|
||||||
|
self->entries.capacity = 0;
|
||||||
|
self->entries.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t symtable_declare(symtable* self, char const* name, type* ty)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if (self->entries.size >= self->entries.capacity)
|
||||||
|
{
|
||||||
|
self->entries.capacity *= 2;
|
||||||
|
|
||||||
|
self->entries.data = realloc(
|
||||||
|
self->entries.data,
|
||||||
|
sizeof(symentry*)
|
||||||
|
* self->entries.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->entries.data[self->entries.size] =
|
||||||
|
malloc(sizeof(symentry));
|
||||||
|
|
||||||
|
|
||||||
|
self->entries.data[self->entries.size]->name = str_new(name);
|
||||||
|
self->entries.data[self->entries.size]->ty = type_new_clone(ty);
|
||||||
|
self->entries.data[self->entries.size]->id = self->id;
|
||||||
|
self->entries.size++;
|
||||||
|
|
||||||
|
return self->id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
symentry* symtable_find(symtable* self, char const* name)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(self->entries.data[i]->name, name) == 0)
|
||||||
|
{
|
||||||
|
return self->entries.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef SYMTABLE_H
|
||||||
|
#define SYMTABLE_H
|
||||||
|
|
||||||
|
#include "commons.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t id;
|
||||||
|
char* name;
|
||||||
|
type* ty;
|
||||||
|
} symentry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
size_t size;
|
||||||
|
size_t capacity;
|
||||||
|
symentry** data;
|
||||||
|
} entries;
|
||||||
|
|
||||||
|
size_t id;
|
||||||
|
} symtable;
|
||||||
|
|
||||||
|
void symtable_init(symtable* self);
|
||||||
|
void symtable_free(symtable* self);
|
||||||
|
|
||||||
|
size_t symtable_declare(symtable* self, char const* name, type* ty);
|
||||||
|
symentry* symtable_find(symtable* self, char const* name);
|
||||||
|
|
||||||
|
#endif
|
239
src/vm.c
239
src/vm.c
|
@ -8,6 +8,10 @@ void vm_init(vm* self)
|
||||||
self->stack.capacity = 1;
|
self->stack.capacity = 1;
|
||||||
self->stack.data = malloc(sizeof(value*) * self->stack.capacity);
|
self->stack.data = malloc(sizeof(value*) * self->stack.capacity);
|
||||||
|
|
||||||
|
self->vars.size = 0;
|
||||||
|
self->vars.capacity = 1;
|
||||||
|
self->vars.data = malloc(sizeof(var*) * self->vars.capacity);
|
||||||
|
|
||||||
self->prog = NULL;
|
self->prog = NULL;
|
||||||
self->pc = 0;
|
self->pc = 0;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +19,16 @@ void vm_init(vm* self)
|
||||||
void vm_free(vm* self)
|
void vm_free(vm* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->vars.size; i++)
|
||||||
|
{
|
||||||
|
value_free(self->vars.data[i]->val);
|
||||||
|
free(self->vars.data[i]->val);
|
||||||
|
free(self->vars.data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(self->vars.data);
|
||||||
|
|
||||||
for (size_t i=0; i<self->stack.size; i++)
|
for (size_t i=0; i<self->stack.size; i++)
|
||||||
{
|
{
|
||||||
value_free(self->stack.data[i]);
|
value_free(self->stack.data[i]);
|
||||||
|
@ -76,6 +90,19 @@ void vm_exec(vm* self, program* prog)
|
||||||
case OP_TMUL: vm_tmul(self); break;
|
case OP_TMUL: vm_tmul(self); break;
|
||||||
case OP_TADD: vm_tadd(self); break;
|
case OP_TADD: vm_tadd(self); break;
|
||||||
|
|
||||||
|
case OP_ILT: vm_ilt(self); break;
|
||||||
|
case OP_ILE: vm_ile(self); break;
|
||||||
|
case OP_IGT: vm_igt(self); break;
|
||||||
|
case OP_IGE: vm_ige(self); break;
|
||||||
|
|
||||||
|
case OP_FLT: vm_flt(self); break;
|
||||||
|
case OP_FLE: vm_fle(self); break;
|
||||||
|
case OP_FGT: vm_fgt(self); break;
|
||||||
|
case OP_FGE: vm_fge(self); break;
|
||||||
|
|
||||||
|
case OP_LOAD: vm_load(self, param); break;
|
||||||
|
case OP_STORE: vm_store(self, param); break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
OpcodesStr[opcode]);
|
OpcodesStr[opcode]);
|
||||||
|
@ -135,6 +162,41 @@ size_t vm_str(vm* self, char* buffer, size_t size)
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_set(vm* self, size_t addr, value* val)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
assert(val);
|
||||||
|
|
||||||
|
if (self->vars.size > self->vars.capacity)
|
||||||
|
{
|
||||||
|
self->vars.capacity *= 2;
|
||||||
|
self->vars.data = realloc(
|
||||||
|
self->vars.data,
|
||||||
|
sizeof(var*) * self->vars.capacity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
self->vars.data[self->vars.size] = malloc(sizeof(var));
|
||||||
|
self->vars.data[self->vars.size]->addr = addr;
|
||||||
|
self->vars.data[self->vars.size]->val = value_new_clone(val);
|
||||||
|
self->vars.size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
value* vm_get(vm* self, size_t addr)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->vars.size; i++)
|
||||||
|
{
|
||||||
|
if (self->vars.data[i]->addr == addr)
|
||||||
|
{
|
||||||
|
return value_new_clone(self->vars.data[i]->val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void vm_push(vm* self, int param)
|
void vm_push(vm* self, int param)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -740,3 +802,180 @@ void vm_tadd(vm* self)
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_flt(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.real_float < rhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_fle(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.real_float <= rhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_fgt(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.real_float > rhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_fge(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.real_float >= rhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_ilt(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.integer < rhs->val.integer, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_ile(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.integer <= rhs->val.integer, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_igt(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.integer > rhs->val.integer, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_ige(vm* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_boolean(val, lhs->val.integer >= rhs->val.integer, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(rhs);
|
||||||
|
free(rhs);
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_store(vm* self, int param)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* val = vm_pop_value(self);
|
||||||
|
|
||||||
|
vm_set(self, param, val);
|
||||||
|
|
||||||
|
value_free(val);
|
||||||
|
free(val);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_load(vm* self, int param)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
value* val = vm_get(self, param);
|
||||||
|
assert(val);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
27
src/vm.h
27
src/vm.h
|
@ -5,12 +5,23 @@
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t addr;
|
||||||
|
value* val;
|
||||||
|
} var;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct {
|
struct {
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t size;
|
size_t size;
|
||||||
value** data;
|
value** data;
|
||||||
} stack;
|
} stack;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
size_t capacity;
|
||||||
|
size_t size;
|
||||||
|
var** data;
|
||||||
|
} vars;
|
||||||
|
|
||||||
size_t pc;
|
size_t pc;
|
||||||
program* prog;
|
program* prog;
|
||||||
|
@ -24,6 +35,9 @@ void vm_push_value(vm* self, value* val);
|
||||||
value* vm_pop_value(vm* self);
|
value* vm_pop_value(vm* self);
|
||||||
size_t vm_str(vm* self, char* buffer, size_t size);
|
size_t vm_str(vm* self, char* buffer, size_t size);
|
||||||
|
|
||||||
|
void vm_set(vm* self, size_t addr, value* val);
|
||||||
|
value* vm_get(vm* self, size_t addr);
|
||||||
|
|
||||||
void vm_push(vm* self, int param);
|
void vm_push(vm* self, int param);
|
||||||
void vm_and(vm* self);
|
void vm_and(vm* self);
|
||||||
void vm_or(vm* self);
|
void vm_or(vm* self);
|
||||||
|
@ -60,4 +74,17 @@ void vm_amul(vm* self);
|
||||||
void vm_tmul(vm* self);
|
void vm_tmul(vm* self);
|
||||||
void vm_tadd(vm* self);
|
void vm_tadd(vm* self);
|
||||||
|
|
||||||
|
void vm_ilt(vm* self);
|
||||||
|
void vm_ile(vm* self);
|
||||||
|
void vm_igt(vm* self);
|
||||||
|
void vm_ige(vm* self);
|
||||||
|
|
||||||
|
void vm_flt(vm* self);
|
||||||
|
void vm_fle(vm* self);
|
||||||
|
void vm_fgt(vm* self);
|
||||||
|
void vm_fge(vm* self);
|
||||||
|
|
||||||
|
void vm_store(vm* self, int param);
|
||||||
|
void vm_load(vm* self, int param);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
5 < 5.2
|
||||||
|
5 > 5.2
|
||||||
|
5 <= 5.2
|
||||||
|
5 >= 5.2
|
||||||
|
|
||||||
|
52.3 < 5
|
||||||
|
5.7 > 5
|
||||||
|
5.28 <= 2
|
||||||
|
5.34 >= 2
|
||||||
|
|
||||||
|
52.3 < bool
|
||||||
|
5.7 > bool
|
||||||
|
5.28 <= bool
|
||||||
|
5.34 >= bool
|
||||||
|
|
||||||
|
bool < bool
|
||||||
|
bool > bool
|
||||||
|
bool <= bool
|
||||||
|
bool >= bool
|
||||||
|
|
||||||
|
str < str
|
||||||
|
str > str
|
||||||
|
str <= str
|
||||||
|
str >= str
|
|
@ -0,0 +1,3 @@
|
||||||
|
let x = 0 x + 1.2
|
||||||
|
let x = false x + "false"
|
||||||
|
let x=0 let x=7
|
|
@ -0,0 +1,33 @@
|
||||||
|
assert 4 < 10
|
||||||
|
assert !(16 < 15)
|
||||||
|
assert !(36 < 36)
|
||||||
|
|
||||||
|
assert 9 <= 15
|
||||||
|
assert !(19 <= 3)
|
||||||
|
assert 37 <= 37
|
||||||
|
|
||||||
|
assert 100 > 10
|
||||||
|
assert !(99 > 215)
|
||||||
|
assert !(33 > 33)
|
||||||
|
|
||||||
|
assert 29 >= 2
|
||||||
|
assert !(296 >= 720)
|
||||||
|
assert 348 >= 348
|
||||||
|
|
||||||
|
assert 4.0 < 10.0
|
||||||
|
assert !(16.0 < 15.0)
|
||||||
|
assert !(36.0 < 36.0)
|
||||||
|
|
||||||
|
assert 9.0 <= 15.0
|
||||||
|
assert !(19.0 <= 3.0)
|
||||||
|
assert 37.0 <= 37.0
|
||||||
|
|
||||||
|
assert 100.0 > 10.0
|
||||||
|
assert !(99.0 > 215.0)
|
||||||
|
assert !(33.0 > 33.0)
|
||||||
|
|
||||||
|
assert 29.0 >= 2.0
|
||||||
|
assert !(296.0 >= 720.0)
|
||||||
|
assert 348.0 >= 348.0
|
||||||
|
|
||||||
|
assert 5 > 3 == true
|
|
@ -0,0 +1,5 @@
|
||||||
|
let a = 4
|
||||||
|
let b = 7
|
||||||
|
let c = a * b + 1
|
||||||
|
|
||||||
|
assert 29 == c
|
Loading…
Reference in New Issue