Compare commits

..

2 Commits

Author SHA1 Message Date
bog 74e5f5225d if expressions. 2024-04-02 19:16:22 +02:00
bog 8e9b6f956d variables and constants. 2024-04-02 17:33:31 +02:00
22 changed files with 1019 additions and 56 deletions

View File

@ -2,6 +2,16 @@ ROOT ::= EXPR*
EXPR ::= EXPR ::=
| OR | OR
| ASSERT | ASSERT
| VAR_DECL
| CONST_DECL
| ASSIGN
| BLOCK
| IF
IF ::= if EXPR BLOCK (else (BLOCK | IF))?
BLOCK ::= begin EXPR* end
ASSIGN ::= ident assign EXPR
VAR_DECL ::= var ident assign EXPR
CONST_DECL ::= const ident assign EXPR
ASSERT ::= assert EXPR eq EXPR ASSERT ::= assert EXPR eq EXPR
OR ::= AND (or AND)* OR ::= AND (or AND)*
AND ::= EQ (and EQ)* AND ::= EQ (and EQ)*
@ -15,6 +25,7 @@ POW ::= LITERAL (pow LITERAL)?
LITERAL ::= LITERAL ::=
| BUILTIN | BUILTIN
| opar EXPR cpar | opar EXPR cpar
| ident
BUILTIN ::= BUILTIN ::=
| int | int
| bool | bool

62
features/conds.sk Normal file
View File

@ -0,0 +1,62 @@
var a = 4
if true
a = 5
end
assert a eq 5
if false
a = 12
end
assert a eq 5
if true
a = 1
else if true
a = 2
else if true
a = 3
else
a = 4
end
assert a eq 1
if false
a = 1
else if true
a = 2
else if true
a = 3
else
a = 4
end
assert a eq 2
if false
a = 1
else if false
a = 2
else if true
a = 3
else
a = 4
end
assert a eq 3
if false
a = 1
else if false
a = 2
else if false
a = 3
else
a = 4
end
assert a eq 4

20
features/vars.sk Normal file
View File

@ -0,0 +1,20 @@
var a = 32
assert a eq 32
a = 7
2
assert a eq 7
a = a + 1
assert a eq 8
begin
assert a eq 8
a = 9
var a = "hop"
assert a eq "hop"
a = 27
assert a eq 27
end
assert a eq 9

View File

@ -22,6 +22,8 @@ add_library(skopy-lib SHARED
src/module.c src/module.c
src/errors.c src/errors.c
src/sym.c
) )
file(GLOB_RECURSE file(GLOB_RECURSE

View File

@ -3,6 +3,7 @@
#include "commons.h" #include "commons.h"
#include "prog.h" #include "prog.h"
#include "sym.h"
struct compiler struct compiler
{ {
@ -13,11 +14,13 @@ void compiler_free(struct compiler* self);
void compiler_compile(struct compiler* self, void compiler_compile(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog); struct prog* prog,
struct sym* sym);
void compiler_compile_children(struct compiler* self, void compiler_compile_children(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog); struct prog* prog,
struct sym* sym);
void compiler_compile_value(struct compiler* self, void compiler_compile_value(struct compiler* self,
struct node* node, struct node* node,
@ -27,10 +30,18 @@ void compiler_compile_value(struct compiler* self,
void compiler_compile_and(struct compiler* self, void compiler_compile_and(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog); struct prog* prog,
struct sym* sym);
void compiler_compile_or(struct compiler* self, void compiler_compile_or(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog); struct prog* prog,
struct sym* sym);
void compiler_compile_if(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct vec* to_end);
#endif #endif

View File

@ -26,12 +26,15 @@ void lexer_skip_comments(struct lexer* self);
bool lexer_is_sep(struct lexer* self, size_t index); bool lexer_is_sep(struct lexer* self, size_t index);
bool lexer_next_is(struct lexer* self, TokenKind kind); bool lexer_next_is(struct lexer* self, TokenKind kind);
bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth);
void lexer_consume_next(struct lexer* self); void lexer_consume_next(struct lexer* self);
struct token* lexer_try_new_next(struct lexer* self); struct token* lexer_try_new_next(struct lexer* self);
struct token* lexer_try_scan_int(struct lexer* self); struct token* lexer_try_scan_int(struct lexer* self);
struct token* lexer_try_scan_float(struct lexer* self); struct token* lexer_try_scan_float(struct lexer* self);
struct token* lexer_try_scan_string(struct lexer* self); struct token* lexer_try_scan_string(struct lexer* self);
struct token* lexer_try_scan_ident(struct lexer* self);
bool lexer_is_ident(struct lexer* self, size_t index);
struct token* lexer_try_scan_text(struct lexer* self, struct token* lexer_try_scan_text(struct lexer* self,
char const* text, char const* text,
TokenKind kind); TokenKind kind);

View File

@ -3,11 +3,13 @@
#include "commons.h" #include "commons.h"
#include "prog.h" #include "prog.h"
#include "sym.h"
struct module struct module
{ {
struct str source; struct str source;
struct prog prog; struct prog prog;
struct sym sym;
}; };
void module_init(struct module* self); void module_init(struct module* self);

View File

@ -12,7 +12,9 @@ G(NODE_USUB), G(NODE_ASSERT_EQ), \
G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \ G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \
G(NODE_NOT), G(NODE_FLOAT), G(NODE_STRING), \ G(NODE_NOT), G(NODE_FLOAT), G(NODE_STRING), \
G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \ G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \
G(NODE_EQUAL), G(NODE_NOT_EQUAL) G(NODE_EQUAL), G(NODE_NOT_EQUAL), G(NODE_VAR_DECL), \
G(NODE_CONST_DECL), G(NODE_IDENT), G(NODE_ASSIGN), \
G(NODE_BLOCK), G(NODE_IF)
SK_ENUM_H(NodeKind, NODE_KIND); SK_ENUM_H(NodeKind, NODE_KIND);

View File

@ -19,6 +19,12 @@ struct node* parser_try(struct parser* self,
struct node* parser_try_parse(struct parser* self); struct node* parser_try_parse(struct parser* self);
struct node* parser_try_root(struct parser* self); struct node* parser_try_root(struct parser* self);
struct node* parser_try_expr(struct parser* self); struct node* parser_try_expr(struct parser* self);
struct node* parser_try_block(struct parser* self);
struct node* parser_try_inner_block(struct parser* self);
struct node* parser_try_if(struct parser* self);
struct node* parser_try_assign(struct parser* self);
struct node* parser_try_var_decl(struct parser* self);
struct node* parser_try_const_decl(struct parser* self);
struct node* parser_try_assert(struct parser* self); struct node* parser_try_assert(struct parser* self);
struct node* parser_try_or(struct parser* self); struct node* parser_try_or(struct parser* self);
struct node* parser_try_and(struct parser* self); struct node* parser_try_and(struct parser* self);

View File

@ -12,7 +12,7 @@ G(OP_DIV), G(OP_MOD), G(OP_POW), \
G(OP_USUB), G(OP_ASSERT_EQ), \ G(OP_USUB), G(OP_ASSERT_EQ), \
G(OP_NOT), G(OP_AND), G(OP_OR), \ G(OP_NOT), G(OP_AND), G(OP_OR), \
G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \ G(OP_BR), G(OP_BRF), G(OP_LT), G(OP_GT), \
G(OP_EQUAL) G(OP_EQUAL), G(OP_LOCAL_STORE), G(OP_LOCAL_LOAD)
SK_ENUM_H(Opcode, OPCODE); SK_ENUM_H(Opcode, OPCODE);

View File

@ -3,9 +3,17 @@
#include "commons.h" #include "commons.h"
#include "value.h" #include "value.h"
#define SK size_t #define SK size_t
#define SK_NO_ID (-1)
struct local struct local
{
int id;
size_t addr;
};
struct stack_value
{ {
size_t addr; size_t addr;
struct value* value; struct value* value;
@ -13,6 +21,7 @@ struct local
struct frame struct frame
{ {
struct vec stack_values;
struct vec locals; struct vec locals;
struct vec stack; struct vec stack;
}; };
@ -23,11 +32,11 @@ struct state
size_t addr; size_t addr;
}; };
void local_init(struct local* self, void stack_value_init(struct stack_value* self,
size_t addr, size_t addr,
struct value* new_value); struct value* new_value);
void local_free(struct local* self); void stack_value_free(struct stack_value* self);
void frame_init(struct frame* self); void frame_init(struct frame* self);
void frame_free(struct frame* self); void frame_free(struct frame* self);
@ -54,6 +63,14 @@ SK state_push_bool(struct state* self, bool boolean, int line);
SK state_push_float(struct state* self, double real, int line); SK state_push_float(struct state* self, double real, int line);
SK state_push_string(struct state* self, char const* str, int line); SK state_push_string(struct state* self, char const* str, int line);
struct local* state_try_get_local(struct state* self, int id);
SK state_local_store(struct state* self,
int id);
void state_local_load(struct state* self,
int id);
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs); TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs);
TypeKind state_type(struct state* self, SK value); TypeKind state_type(struct state* self, SK value);
double state_as_real(struct state* self, SK lhs); double state_as_real(struct state* self, SK lhs);

48
lib/include/sym.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef SK_SYM_H
#define SK_SYM_H
#include "commons.h"
struct symbol
{
int id;
char* name;
bool is_const;
struct env* env;
};
struct env
{
struct vec symbols;
struct env* parent;
};
struct sym
{
int id_counter;
struct env* env;
};
void env_init(struct env* self);
void env_free(struct env* self);
struct symbol* env_try_get(struct env* self, char const* name);
void symbol_init(struct symbol* self,
int id,
char const* name,
struct env* env);
void symbol_free(struct symbol* self);
void sym_init(struct sym* self);
void sym_free(struct sym* self);
int sym_decl_var(struct sym* self, char const* name);
int sym_decl_const(struct sym* self, char const* name);
void sym_open_scope(struct sym* self);
void sym_close_scope(struct sym* self);
struct symbol* sym_try_get(struct sym* self, char const* name);
#endif

View File

@ -13,7 +13,9 @@ G(TOKEN_ASSERT), G(TOKEN_ASSERT_EQ), \
G(TOKEN_BOOL), G(TOKEN_AND), G(TOKEN_OR), \ G(TOKEN_BOOL), G(TOKEN_AND), G(TOKEN_OR), \
G(TOKEN_NOT), G(TOKEN_FLOAT), G(TOKEN_STRING), \ G(TOKEN_NOT), G(TOKEN_FLOAT), G(TOKEN_STRING), \
G(TOKEN_LT), G(TOKEN_LE), G(TOKEN_GT), G(TOKEN_GE), \ G(TOKEN_LT), G(TOKEN_LE), G(TOKEN_GT), G(TOKEN_GE), \
G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL) G(TOKEN_EQUAL), G(TOKEN_NOT_EQUAL), G(TOKEN_VAR), \
G(TOKEN_CONST), G(TOKEN_ASSIGN), G(TOKEN_IDENT), \
G(TOKEN_BEGIN), G(TOKEN_END), G(TOKEN_IF), G(TOKEN_ELSE)
SK_ENUM_H(TokenKind, TOKEN_KIND); SK_ENUM_H(TokenKind, TOKEN_KIND);

View File

@ -13,7 +13,8 @@ void compiler_free(struct compiler* self)
void compiler_compile(struct compiler* self, void compiler_compile(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog) struct prog* prog,
struct sym* sym)
{ {
assert(self); assert(self);
assert(node); assert(node);
@ -25,28 +26,113 @@ void compiler_compile(struct compiler* self,
for (size_t i=0; i<node->children.size; i++) for (size_t i=0; i<node->children.size; i++)
{ {
compiler_compile(self, node->children.data[i], compiler_compile(self, node->children.data[i],
prog); prog, sym);
} }
} break; } break;
case NODE_BLOCK: {
sym_open_scope(sym);
for (size_t i=0; i<node->children.size; i++)
{
compiler_compile(self, node->children.data[i],
prog, sym);
}
sym_close_scope(sym);
} break;
case NODE_IF: {
struct vec to_end;
vec_init(&to_end);
compiler_compile_if(self, node, prog, sym, &to_end);
size_t end_point = prog->params.size;
for (size_t i=0; i<to_end.size; i++)
{
size_t addr = (size_t) to_end.data[i];
((size_t*) prog->params.data)[addr] = end_point;
}
vec_free(&to_end);
} break;
case NODE_NOT: { case NODE_NOT: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break; } break;
case NODE_AND: { case NODE_AND: {
compiler_compile_and(self, node, prog); compiler_compile_and(self, node, prog, sym);
} break; } break;
case NODE_OR: { case NODE_OR: {
compiler_compile_or(self, node, prog); compiler_compile_or(self, node, prog, sym);
} break; } break;
case NODE_ASSERT_EQ: { case NODE_ASSERT_EQ: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM); prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM);
} break; } break;
case NODE_VAR_DECL: {
struct node* ident = node->children.data[0];
struct symbol const* s = sym_try_get(sym, ident->token->value);
if (s && s->env == sym->env)
{
errors_push(node->token->line, "'%s' is already defined",
ident->token->value);
}
struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym);
int id = sym_decl_var(sym, ident->token->value);
prog_add_instr(prog, OP_LOCAL_STORE, id);
} break;
case NODE_CONST_DECL: {
struct node* ident = node->children.data[0];
struct symbol const* s = sym_try_get(sym, ident->token->value);
if (s && s->env == sym->env)
{
errors_push(node->token->line, "'%s' is already defined",
ident->token->value);
}
struct node* expr = node->children.data[1];
compiler_compile(self, expr, prog, sym);
int id = sym_decl_const(sym, ident->token->value);
prog_add_instr(prog, OP_LOCAL_STORE, id);
} break;
case NODE_ASSIGN: {
struct node* ident = node->children.data[0];
struct node* expr = node->children.data[1];
struct symbol* symbol = sym_try_get(sym, ident->token->value);
if (!symbol)
{
errors_push(ident->token->line, "'%s' is not defined",
ident->token->value);
break;
}
if (symbol->is_const)
{
errors_push(ident->token->line, "'%s' is not mutable",
ident->token->value);
break;
}
compiler_compile(self, expr, prog, sym);
prog_add_instr(prog, OP_LOCAL_STORE, symbol->id);
} break;
case NODE_IDENT: {
struct symbol* symbol = sym_try_get(sym,
node->token->value);
assert(symbol);
prog_add_instr(prog, OP_LOCAL_LOAD, symbol->id);
} break;
case NODE_BOOL: { case NODE_BOOL: {
union val val; union val val;
val.boolean = val.boolean =
@ -77,70 +163,70 @@ void compiler_compile(struct compiler* self,
} break; } break;
case NODE_LT: { case NODE_LT: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_LT, SK_NO_PARAM); prog_add_instr(prog, OP_LT, SK_NO_PARAM);
} break; } break;
case NODE_LE: { case NODE_LE: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_GT, SK_NO_PARAM); prog_add_instr(prog, OP_GT, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break; } break;
case NODE_GT: { case NODE_GT: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_GT, SK_NO_PARAM); prog_add_instr(prog, OP_GT, SK_NO_PARAM);
} break; } break;
case NODE_GE: { case NODE_GE: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_LT, SK_NO_PARAM); prog_add_instr(prog, OP_LT, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break; } break;
case NODE_EQUAL: { case NODE_EQUAL: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM); prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
} break; } break;
case NODE_NOT_EQUAL: { case NODE_NOT_EQUAL: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM); prog_add_instr(prog, OP_EQUAL, SK_NO_PARAM);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM); prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break; } break;
case NODE_ADD: { case NODE_ADD: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_ADD, SK_NO_PARAM); prog_add_instr(prog, OP_ADD, SK_NO_PARAM);
} break; } break;
case NODE_SUB: { case NODE_SUB: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_SUB, SK_NO_PARAM); prog_add_instr(prog, OP_SUB, SK_NO_PARAM);
} break; } break;
case NODE_MUL: { case NODE_MUL: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_MUL, SK_NO_PARAM); prog_add_instr(prog, OP_MUL, SK_NO_PARAM);
} break; } break;
case NODE_DIV: { case NODE_DIV: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_DIV, SK_NO_PARAM); prog_add_instr(prog, OP_DIV, SK_NO_PARAM);
} break; } break;
case NODE_MOD: { case NODE_MOD: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_MOD, SK_NO_PARAM); prog_add_instr(prog, OP_MOD, SK_NO_PARAM);
} break; } break;
case NODE_POW: { case NODE_POW: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_POW, SK_NO_PARAM); prog_add_instr(prog, OP_POW, SK_NO_PARAM);
} break; } break;
case NODE_USUB: { case NODE_USUB: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog, sym);
prog_add_instr(prog, OP_USUB, SK_NO_PARAM); prog_add_instr(prog, OP_USUB, SK_NO_PARAM);
} break; } break;
@ -154,7 +240,8 @@ void compiler_compile(struct compiler* self,
void compiler_compile_children(struct compiler* self, void compiler_compile_children(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog) struct prog* prog,
struct sym* sym)
{ {
assert(self); assert(self);
assert(node); assert(node);
@ -163,7 +250,7 @@ void compiler_compile_children(struct compiler* self,
for (size_t i=0; i<node->children.size; i++) for (size_t i=0; i<node->children.size; i++)
{ {
struct node* child = node->children.data[i]; struct node* child = node->children.data[i];
compiler_compile(self, child, prog); compiler_compile(self, child, prog, sym);
} }
} }
@ -184,11 +271,13 @@ void compiler_compile_value(struct compiler* self,
void compiler_compile_and(struct compiler* self, void compiler_compile_and(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog) struct prog* prog,
struct sym* sym)
{ {
assert(self); assert(self);
assert(node); assert(node);
assert(prog); assert(prog);
assert(sym);
struct vec to_false; struct vec to_false;
vec_init(&to_false); vec_init(&to_false);
@ -196,7 +285,7 @@ void compiler_compile_and(struct compiler* self,
for (size_t i =0; i<node->children.size; i++) for (size_t i =0; i<node->children.size; i++)
{ {
struct node* child = node->children.data[i]; struct node* child = node->children.data[i];
compiler_compile(self, child, prog); compiler_compile(self, child, prog, sym);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false
vec_push(&to_false, (void*) brf); vec_push(&to_false, (void*) brf);
} }
@ -225,19 +314,20 @@ void compiler_compile_and(struct compiler* self,
void compiler_compile_or(struct compiler* self, void compiler_compile_or(struct compiler* self,
struct node* node, struct node* node,
struct prog* prog) struct prog* prog,
struct sym* sym)
{ {
assert(self); assert(self);
assert(node); assert(node);
assert(prog); assert(prog);
assert(sym);
struct vec to_true; struct vec to_true;
vec_init(&to_true); vec_init(&to_true);
for (size_t i =0; i<node->children.size; i++) for (size_t i =0; i<node->children.size; i++)
{ {
struct node* child = node->children.data[i]; struct node* child = node->children.data[i];
compiler_compile(self, child, prog); compiler_compile(self, child, prog, sym);
prog_add_instr(prog, OP_NOT, 0); prog_add_instr(prog, OP_NOT, 0);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true
vec_push(&to_true, (void*) brf); vec_push(&to_true, (void*) brf);
@ -264,3 +354,37 @@ void compiler_compile_or(struct compiler* self,
vec_free(&to_true); vec_free(&to_true);
} }
void compiler_compile_if(struct compiler* self,
struct node* node,
struct prog* prog,
struct sym* sym,
struct vec* to_end)
{
struct node* cond = node->children.data[0];
struct node* block = node->children.data[1];
compiler_compile(self, cond, prog, sym);
size_t brf = prog_add_instr(prog, OP_BRF, 40); // to next
compiler_compile(self, block, prog, sym);
size_t br = prog_add_instr(prog, OP_BR, 0); // to end
vec_push(to_end, (void*) br);
size_t next_point = prog->opcodes.size;
((size_t*)prog->params.data)[brf] = next_point;
if (node->children.size == 3)
{
struct node* next = node->children.data[2];
if (next->kind == NODE_IF)
{
compiler_compile_if(self, next, prog, sym, to_end);
}
else
{
compiler_compile(self, next, prog, sym);
}
}
}

View File

@ -27,6 +27,16 @@ void exec_execute(struct exec* self,
switch (opcode) switch (opcode)
{ {
case OP_LOCAL_STORE: {
state_local_store(state, param);
self->pc++;
} break;
case OP_LOCAL_LOAD: {
state_local_load(state, param);
self->pc++;
} break;
case OP_ASSERT_EQ: { case OP_ASSERT_EQ: {
SK rhs = state_pop(state); SK rhs = state_pop(state);
SK lhs = state_pop(state); SK lhs = state_pop(state);

View File

@ -92,6 +92,34 @@ bool lexer_is_sep(struct lexer* self, size_t index)
|| c == '='; || c == '=';
} }
bool lexer_next_nth_is(struct lexer* self, TokenKind kind, int nth)
{
assert(self);
struct context ctx = self->context;
bool res = false;
for (int i=0; i<=nth; i++)
{
struct token* tok = lexer_try_new_next(self);
if (!tok)
{
self->context = ctx;
return false;
}
res = tok->kind == kind;
token_free(tok);
free(tok);
}
self->context = ctx;
return res;
}
bool lexer_next_is(struct lexer* self, TokenKind kind) bool lexer_next_is(struct lexer* self, TokenKind kind)
{ {
struct context ctx = self->context; struct context ctx = self->context;
@ -100,6 +128,7 @@ bool lexer_next_is(struct lexer* self, TokenKind kind)
if (!tok) if (!tok)
{ {
self->context = ctx;
return false; return false;
} }
@ -108,7 +137,6 @@ bool lexer_next_is(struct lexer* self, TokenKind kind)
free(tok); free(tok);
self->context = ctx; self->context = ctx;
return res; return res;
} }
@ -164,6 +192,13 @@ struct token* lexer_try_new_next(struct lexer* self)
SK_SCAN_TEXT(")", TOKEN_CPAR); SK_SCAN_TEXT(")", TOKEN_CPAR);
SK_SCAN_TEXT(">", TOKEN_GT); SK_SCAN_TEXT(">", TOKEN_GT);
SK_SCAN_TEXT("<", TOKEN_LT); SK_SCAN_TEXT("<", TOKEN_LT);
SK_SCAN_TEXT("=", TOKEN_ASSIGN);
SK_SCAN_KEYWORD("if", TOKEN_IF, NULL);
SK_SCAN_KEYWORD("else", TOKEN_ELSE, NULL);
SK_SCAN_KEYWORD("begin", TOKEN_BEGIN, NULL);
SK_SCAN_KEYWORD("end", TOKEN_END, NULL);
SK_SCAN_KEYWORD("var", TOKEN_VAR, NULL);
SK_SCAN_KEYWORD("const", TOKEN_CONST, NULL);
SK_SCAN_KEYWORD("assert", TOKEN_ASSERT, NULL); SK_SCAN_KEYWORD("assert", TOKEN_ASSERT, NULL);
SK_SCAN_KEYWORD("eq", TOKEN_ASSERT_EQ, NULL); SK_SCAN_KEYWORD("eq", TOKEN_ASSERT_EQ, NULL);
SK_SCAN_KEYWORD("true", TOKEN_BOOL, "true"); SK_SCAN_KEYWORD("true", TOKEN_BOOL, "true");
@ -173,6 +208,11 @@ struct token* lexer_try_new_next(struct lexer* self)
SK_SCAN_KEYWORD("not", TOKEN_NOT, NULL); SK_SCAN_KEYWORD("not", TOKEN_NOT, NULL);
if ( (tok=lexer_try_scan_ident(self)) )
{
return tok;
}
if (self->context.cursor < self->len) if (self->context.cursor < self->len)
{ {
struct str str; struct str str;
@ -352,6 +392,47 @@ struct token* lexer_try_scan_string(struct lexer* self)
return tok; return tok;
} }
struct token* lexer_try_scan_ident(struct lexer* self)
{
assert(self);
size_t cursor = self->context.cursor;
struct str value;
str_init(&value);
while (cursor < self->len
&& lexer_is_ident(self, cursor))
{
str_push(&value, self->source[cursor]);
cursor++;
}
struct token* tok = NULL;
if (value.size > 0 && !isdigit(value.value[0]))
{
tok = malloc(sizeof(struct token));
token_init(tok, TOKEN_IDENT,
value.value, self->context.line);
self->context.cursor = cursor;
}
str_free(&value);
return tok;
}
bool lexer_is_ident(struct lexer* self, size_t index)
{
assert(self);
if (index >= self->len) { return false; }
char c = self->source[index];
return isalnum(c)
|| c == '_'
|| c == '!'
|| c == '?';
}
struct token* lexer_try_scan_text(struct lexer* self, struct token* lexer_try_scan_text(struct lexer* self,
char const* text, char const* text,
TokenKind kind) TokenKind kind)

View File

@ -9,6 +9,7 @@ void module_init(struct module* self)
assert(self); assert(self);
str_init(&self->source); str_init(&self->source);
prog_init(&self->prog); prog_init(&self->prog);
sym_init(&self->sym);
} }
void module_free(struct module* self) void module_free(struct module* self)
@ -16,6 +17,7 @@ void module_free(struct module* self)
assert(self); assert(self);
str_free(&self->source); str_free(&self->source);
prog_free(&self->prog); prog_free(&self->prog);
sym_free(&self->sym);
} }
void module_load_source(struct module* self, void module_load_source(struct module* self,
@ -52,7 +54,7 @@ int module_compile(struct module* self)
struct compiler compiler; struct compiler compiler;
compiler_init(&compiler); compiler_init(&compiler);
compiler_compile(&compiler, root, &self->prog); compiler_compile(&compiler, root, &self->prog, &self->sym);
struct exec exec; struct exec exec;
exec_init(&exec); exec_init(&exec);

View File

@ -94,9 +94,304 @@ struct node* parser_try_expr(struct parser* self)
return SK_TRY(parser_try_assert); return SK_TRY(parser_try_assert);
} }
if (lexer_next_is(&self->lexer, TOKEN_CONST))
{
return SK_TRY(parser_try_const_decl);
}
if (lexer_next_is(&self->lexer, TOKEN_IDENT)
&& lexer_next_nth_is(&self->lexer, TOKEN_ASSIGN, 1))
{
return SK_TRY(parser_try_assign);
}
if (lexer_next_is(&self->lexer, TOKEN_VAR))
{
return SK_TRY(parser_try_var_decl);
}
if (lexer_next_is(&self->lexer, TOKEN_BEGIN))
{
return SK_TRY(parser_try_block);
}
if (lexer_next_is(&self->lexer, TOKEN_IF))
{
return SK_TRY(parser_try_if);
}
return SK_TRY(parser_try_or); return SK_TRY(parser_try_or);
} }
struct node* parser_try_block(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_BEGIN))
{
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* node = SK_TRY(parser_try_inner_block);
if (!node)
{
token_free(tok); free(tok);
return NULL;
}
if (!lexer_next_is(&self->lexer, TOKEN_END))
{
node_free(node); free(node);
return NULL;
}
lexer_consume_next(&self->lexer);
return node;
}
struct node* parser_try_inner_block(struct parser* self)
{
assert(self);
struct node* node = malloc(sizeof(struct node));
struct token* tok = malloc(sizeof(struct token));
token_init(tok, TOKEN_BEGIN, "", self->lexer.context.line);
node_init(node, NODE_BLOCK, tok);
while (true)
{
struct node* child = SK_TRY(parser_try_expr);
if (!child)
{
break;
}
node_push_new_child(node, child);
}
return node;
}
struct node* parser_try_if(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_IF))
{
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* cond = SK_TRY(parser_try_expr);
if (!cond)
{
token_free(tok); free(tok);
return NULL;
}
struct node* block = SK_TRY(parser_try_inner_block);
if (0&&lexer_next_is(&self->lexer, TOKEN_END))
{
lexer_consume_next(&self->lexer);
}
if (!block)
{
token_free(tok); free(tok);
node_free(cond); free(cond);
return NULL;
}
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_IF, tok);
node_push_new_child(node, cond);
node_push_new_child(node, block);
if (lexer_next_is(&self->lexer, TOKEN_ELSE))
{
lexer_consume_next(&self->lexer);
if (lexer_next_is(&self->lexer, TOKEN_IF))
{
struct node* next = SK_TRY(parser_try_if);
if (!next)
{
token_free(tok); free(tok);
node_free(node); free(node);
return NULL;
}
node_push_new_child(node, next);
}
else
{
struct node* else_block
= SK_TRY(parser_try_inner_block);
if (!else_block)
{
token_free(tok); free(tok);
node_free(node); free(node);
return NULL;
}
node_push_new_child(node, else_block);
if (!lexer_next_is(&self->lexer, TOKEN_END))
{
token_free(tok); free(tok);
node_free(node); free(node);
return NULL;
}
lexer_consume_next(&self->lexer);
}
}
else
{
if (!lexer_next_is(&self->lexer, TOKEN_END))
{
token_free(tok); free(tok);
node_free(node); free(node);
return NULL;
}
lexer_consume_next(&self->lexer);
}
return node;
}
struct node* parser_try_assign(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
{
return NULL;
}
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
{
node_free(ident); free(ident);
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* expr = SK_TRY(parser_try_expr);
if (!expr)
{
node_free(ident); free(ident);
return NULL;
}
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_ASSIGN, tok);
node_push_new_child(node, ident);
node_push_new_child(node, expr);
return node;
}
struct node* parser_try_var_decl(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_VAR))
{
return NULL;
}
lexer_consume_next(&self->lexer);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
{
return NULL;
}
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
{
node_free(ident); free(ident);
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* expr = SK_TRY(parser_try_expr);
if (!expr)
{
node_free(ident); free(ident);
return NULL;
}
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_VAR_DECL, tok);
node_push_new_child(node, ident);
node_push_new_child(node, expr);
return node;
}
struct node* parser_try_const_decl(struct parser* self)
{
assert(self);
if (!lexer_next_is(&self->lexer, TOKEN_CONST))
{
return NULL;
}
lexer_consume_next(&self->lexer);
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
{
return NULL;
}
struct node* ident = malloc(sizeof(struct node));
node_init(ident, NODE_IDENT, lexer_try_new_next(&self->lexer));
if (!lexer_next_is(&self->lexer, TOKEN_ASSIGN))
{
node_free(ident); free(ident);
return NULL;
}
struct token* tok = lexer_try_new_next(&self->lexer);
struct node* expr = SK_TRY(parser_try_expr);
if (!expr)
{
node_free(ident); free(ident);
return NULL;
}
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_CONST_DECL, tok);
node_push_new_child(node, ident);
node_push_new_child(node, expr);
return node;
}
struct node* parser_try_assert(struct parser* self) struct node* parser_try_assert(struct parser* self)
{ {
assert(self); assert(self);
@ -530,6 +825,17 @@ struct node* parser_try_literal(struct parser* self)
return node; return node;
} }
if (lexer_next_is(&self->lexer, TOKEN_IDENT))
{
struct node* node = malloc(sizeof(struct node));
node_init(node,
NODE_IDENT,
lexer_try_new_next(&self->lexer));
return node;
}
return SK_TRY(parser_try_builtin); return SK_TRY(parser_try_builtin);
} }

View File

@ -1,6 +1,6 @@
#include "state.h" #include "state.h"
void local_init(struct local* self, void stack_value_init(struct stack_value* self,
size_t addr, size_t addr,
struct value* new_value) struct value* new_value)
{ {
@ -11,7 +11,7 @@ void local_init(struct local* self,
self->value = new_value; self->value = new_value;
} }
void local_free(struct local* self) void stack_value_free(struct stack_value* self)
{ {
value_free(self->value); value_free(self->value);
free(self->value); free(self->value);
@ -20,13 +20,16 @@ void local_free(struct local* self)
void frame_init(struct frame* self) void frame_init(struct frame* self)
{ {
vec_init(&self->stack_values);
vec_init(&self->locals); vec_init(&self->locals);
vec_init(&self->stack); vec_init(&self->stack);
} }
void frame_free(struct frame* self) void frame_free(struct frame* self)
{ {
vec_free_elements(&self->locals, (void*) local_free); vec_free_elements(&self->stack_values, (void*) stack_value_free);
vec_free(&self->stack_values);
vec_free_elements(&self->locals, NULL);
vec_free(&self->locals); vec_free(&self->locals);
vec_free(&self->stack); vec_free(&self->stack);
} }
@ -83,13 +86,13 @@ struct value* state_try_get_value(struct state* self, SK value)
assert(self); assert(self);
struct frame* frame = state_frame(self); struct frame* frame = state_frame(self);
for (size_t i=0; i<frame->locals.size; i++) for (size_t i=0; i<frame->stack_values.size; i++)
{ {
struct local* local = frame->locals.data[i]; struct stack_value* stack_value = frame->stack_values.data[i];
if (local->addr == value) if (stack_value->addr == value)
{ {
return local->value; return stack_value->value;
} }
} }
@ -118,10 +121,10 @@ SK state_push(struct state* self,
value_init(value, type, val, line); value_init(value, type, val, line);
struct frame* frame = state_frame(self); struct frame* frame = state_frame(self);
struct local* local = malloc(sizeof(struct local)); struct stack_value* stack_value = malloc(sizeof(struct stack_value));
local_init(local, self->addr, value); stack_value_init(stack_value, self->addr, value);
vec_push(&frame->locals, local); vec_push(&frame->stack_values, stack_value);
vec_push(&frame->stack, (void*) self->addr); vec_push(&frame->stack, (void*) self->addr);
self->addr++; self->addr++;
@ -162,6 +165,63 @@ SK state_push_string(struct state* self, char const* str, int line)
return state_push(self, TYPE_STRING, val ,line); return state_push(self, TYPE_STRING, val ,line);
} }
struct local* state_try_get_local(struct state* self, int id)
{
struct frame* frame = state_frame(self);
for (size_t i=0; i<frame->locals.size; i++)
{
struct local* local = frame->locals.data[i];
if (local->id == id)
{
return local;
}
}
return NULL;
}
SK state_local_store(struct state* self,
int id)
{
struct local* local = state_try_get_local(self, id);
if (local)
{
local->addr = state_pop(self);
return local->addr;
}
local = malloc(sizeof(struct local));
local->id = id;
local->addr = state_top(self);
struct frame* frame = state_frame(self);
vec_push(&frame->locals, local);
return local->addr;
}
void state_local_load(struct state* self,
int id)
{
struct frame* frame = state_frame(self);
for (size_t i=0; i<frame->locals.size; i++)
{
struct local* local = frame->locals.data[i];
if (local->id == id)
{
vec_push(&frame->stack, (void*) local->addr);
return;
}
}
assert(0);
}
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs) TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs)
{ {
assert(self); assert(self);

122
lib/src/sym.c Normal file
View File

@ -0,0 +1,122 @@
#include "sym.h"
void env_init(struct env* self)
{
assert(self);
vec_init(&self->symbols);
self->parent = NULL;
}
void env_free(struct env* self)
{
assert(self);
vec_free_elements(&self->symbols, (void*) symbol_free);
vec_free(&self->symbols);
}
struct symbol* env_try_get(struct env* self, char const* name)
{
assert(self);
assert(name);
for (size_t i=0; i<self->symbols.size; i++)
{
struct symbol* symbol = self->symbols.data[i];
if (strcmp(symbol->name, name) == 0)
{
return symbol;
}
}
if (self->parent)
{
return env_try_get(self->parent, name);
}
return NULL;
}
void symbol_init(struct symbol* self,
int id,
char const* name,
struct env* env)
{
assert(self);
self->id = id;
self->name = strdup(name);
self->is_const = false;
self->env = env;
}
void symbol_free(struct symbol* self)
{
assert(self);
free(self->name);
}
void sym_init(struct sym* self)
{
assert(self);
self->id_counter = 1;
self->env = malloc(sizeof(struct env));
env_init(self->env);
}
void sym_free(struct sym* self)
{
assert(self);
env_free(self->env);
free(self->env);
self->env = NULL;
}
int sym_decl_var(struct sym* self, char const* name)
{
assert(self);
assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, self->id_counter, name, self->env);
vec_push(&self->env->symbols, symbol);
self->id_counter++;
return self->id_counter - 1;
}
int sym_decl_const(struct sym* self, char const* name)
{
assert(self);
assert(name);
struct symbol* symbol = malloc(sizeof(struct symbol));
symbol_init(symbol, self->id_counter, name, self->env);
symbol->is_const = true;
vec_push(&self->env->symbols, symbol);
self->id_counter++;
return self->id_counter - 1;
}
void sym_open_scope(struct sym* self)
{
assert(self);
struct env* env = malloc(sizeof(struct env));
env_init(env);
env->parent = self->env;
self->env = env;
}
void sym_close_scope(struct sym* self)
{
assert(self);
struct env* env = self->env;
self->env = env->parent;
env_free(env);
free(env);
}
struct symbol* sym_try_get(struct sym* self, char const* name)
{
return env_try_get(self->env, name);
}

View File

@ -75,6 +75,16 @@ static void test_lexer_bool()
); );
} }
static void test_lexer_decl()
{
test_lexer(" var const = x ", 4,
"VAR",
"CONST",
"ASSIGN",
"IDENT[x]"
);
}
static void test_lexer_float() static void test_lexer_float()
{ {
test_lexer(".4 7. 2.3 6.12", 4, test_lexer(".4 7. 2.3 6.12", 4,
@ -109,6 +119,21 @@ static void test_lexer_cmp()
); );
} }
static void test_lexer_block()
{
test_lexer("begin end", 2,
"BEGIN",
"END"
);
}
static void test_lexer_cond()
{
test_lexer("if else", 2,
"IF",
"ELSE"
);
}
void register_lexer() void register_lexer()
{ {
CU_pSuite suite = CU_add_suite("Lexer", 0, 0); CU_pSuite suite = CU_add_suite("Lexer", 0, 0);
@ -118,6 +143,9 @@ void register_lexer()
CU_add_test(suite, "Floats", test_lexer_float); CU_add_test(suite, "Floats", test_lexer_float);
CU_add_test(suite, "Strings", test_lexer_string); CU_add_test(suite, "Strings", test_lexer_string);
CU_add_test(suite, "Comparisons", test_lexer_cmp); CU_add_test(suite, "Comparisons", test_lexer_cmp);
CU_add_test(suite, "Var Declarations", test_lexer_decl);
CU_add_test(suite, "Blocks", test_lexer_block);
CU_add_test(suite, "Conditionnals", test_lexer_cond);
} }
#endif #endif

View File

@ -87,6 +87,46 @@ static void test_parser_cmp()
"5<>3"); "5<>3");
} }
static void test_parser_decl()
{
test_parser("ROOT(IDENT[bim!])",
"bim!");
test_parser("ROOT(VAR_DECL(IDENT[x],INT[37]))",
"var x = 37");
test_parser("ROOT(CONST_DECL(IDENT[x],MUL(FLOAT[2.2],INT[3])))",
"const x = 2.2 * 3");
}
static void test_parser_assign()
{
test_parser("ROOT(ASSIGN(IDENT[hello],BOOL[false]))",
"hello = false");
}
static void test_parser_block()
{
test_parser("ROOT(BLOCK)",
"begin end");
test_parser("ROOT(BLOCK(INT[1],INT[2]))",
"begin 1 2 end");
}
static void test_parser_if()
{
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0])))",
"if true 0 end");
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0]),BLOCK(INT[1])))",
"if true 0 else 1 end");
test_parser("ROOT(IF(BOOL[true],BLOCK(INT[0]),"
"IF(BOOL[false],BLOCK(INT[1]),BLOCK(INT[2]))))",
"if true 0 else if false 1 else 2 end");
}
void register_parser() void register_parser()
{ {
CU_pSuite suite = CU_add_suite("Parser", 0, 0); CU_pSuite suite = CU_add_suite("Parser", 0, 0);
@ -95,6 +135,10 @@ void register_parser()
CU_add_test(suite, "Booleans", test_parser_bool); CU_add_test(suite, "Booleans", test_parser_bool);
CU_add_test(suite, "Strings", test_parser_string); CU_add_test(suite, "Strings", test_parser_string);
CU_add_test(suite, "Comparisons", test_parser_cmp); CU_add_test(suite, "Comparisons", test_parser_cmp);
CU_add_test(suite, "Declarations", test_parser_decl);
CU_add_test(suite, "Assignments", test_parser_assign);
CU_add_test(suite, "Blocks", test_parser_block);
CU_add_test(suite, "IfExpression", test_parser_if);
} }
#endif #endif