Compare commits

..

2 Commits

Author SHA1 Message Date
bog d8f1af99a6 ADD: let declaration. 2023-08-25 13:41:42 +02:00
bog 299c095af4 ADD/ comparisons operators for integers and floats. 2023-08-25 11:22:29 +02:00
18 changed files with 847 additions and 62 deletions

View File

@ -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

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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))
{ {

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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)

View File

@ -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:

73
src/symtable.c Normal file
View File

@ -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;
}

29
src/symtable.h Normal file
View File

@ -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
View File

@ -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++;
}

View File

@ -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

24
tests/err_cmp.wuz Normal file
View File

@ -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

3
tests/err_vars.wuz Normal file
View File

@ -0,0 +1,3 @@
let x = 0 x + 1.2
let x = false x + "false"
let x=0 let x=7

33
tests/test_cmp.wuz Normal file
View File

@ -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

5
tests/test_vars.wuz Normal file
View File

@ -0,0 +1,5 @@
let a = 4
let b = 7
let c = a * b + 1
assert 29 == c