Compare commits

..

No commits in common. "e7e0789cbb98fa793da8af13b19ea1feda33e594" and "e8b10498cf7b499097359fc03601e5a999b2724f" have entirely different histories.

20 changed files with 70 additions and 1043 deletions

View File

@ -1,20 +1,14 @@
ROOT ::= EXPR* ROOT ::= EXPR*
EXPR ::= EXPR ::=
| OR | TERM
| ASSERT | ASSERT
ASSERT ::= assert EXPR eq EXPR ASSERT ::= assert EXPR eq EXPR
OR ::= AND (or AND)*
AND ::= TERM (and TERM)*
TERM ::= FACTOR ((add|sub) FACTOR)* TERM ::= FACTOR ((add|sub) FACTOR)*
FACTOR ::= USUB ((mul|div|mod) USUB)* FACTOR ::= USUB ((mul|div|mod) USUB)*
USUB ::= sub* NOT USUB ::= sub* POW
NOT ::= not* POW
POW ::= LITERAL (pow LITERAL)? POW ::= LITERAL (pow LITERAL)?
LITERAL ::= LITERAL ::=
| BUILTIN | BUILTIN
| opar EXPR cpar | opar EXPR cpar
BUILTIN ::= BUILTIN ::=
| int | int
| bool
| float
| string

View File

@ -1,15 +0,0 @@
assert true eq true
assert false eq false
assert not true eq false
assert not false eq true
assert true and true eq true
assert true and false eq false
assert false and true eq false
assert false and false eq false
assert true or true eq true
assert true or false eq true
assert false or true eq true
assert false or false eq false

View File

@ -1,10 +0,0 @@
assert 6.200 eq 6.2
assert 5.2 + 1.2 eq 6.4
assert 5.2 - 1.2 eq 4.0
assert 5.2 * 1.2 eq 6.24
assert 5.2 / 2.0 eq 2.6
assert 12.0 % 2.5 eq 2.0
assert 25.0 ^ 0.5 eq 5.0
assert 1 + 1.0 eq 2.0
assert 3.0 * 2 eq 6.0

View File

@ -1,8 +0,0 @@
assert "hello" eq "hello"
assert "hello " + "world" eq "hello world"
assert "a" + "b" + "c" eq "abc"
assert "a" * 3 eq "aaa"
assert 4 * "b" eq "bbbb"
assert ("a" + "b") * 2 eq "abab"

View File

@ -18,19 +18,5 @@ 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);
void compiler_compile_value(struct compiler* self,
struct node* node,
struct prog* prog,
TypeKind type,
union val val);
void compiler_compile_and(struct compiler* self,
struct node* node,
struct prog* prog);
void compiler_compile_or(struct compiler* self,
struct node* node,
struct prog* prog);
#endif #endif

View File

@ -20,9 +20,7 @@ struct lexer
void lexer_init(struct lexer* self, char const* source); void lexer_init(struct lexer* self, char const* source);
void lexer_free(struct lexer* self); void lexer_free(struct lexer* self);
bool lexer_is_at_end(struct lexer* self);
void lexer_skip_spaces(struct lexer* self); void lexer_skip_spaces(struct lexer* self);
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);
@ -30,8 +28,6 @@ bool lexer_next_is(struct lexer* self, TokenKind kind);
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_string(struct lexer* self);
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

@ -8,9 +8,7 @@ G(NODE_ROOT), \
G(NODE_INT), \ G(NODE_INT), \
G(NODE_ADD), G(NODE_SUB), G(NODE_MUL),\ G(NODE_ADD), G(NODE_SUB), G(NODE_MUL),\
G(NODE_DIV), G(NODE_POW), G(NODE_MOD),\ G(NODE_DIV), G(NODE_POW), G(NODE_MOD),\
G(NODE_USUB), G(NODE_ASSERT_EQ), \ G(NODE_USUB), G(NODE_ASSERT_EQ)
G(NODE_BOOL), G(NODE_AND), G(NODE_OR), \
G(NODE_NOT), G(NODE_FLOAT), G(NODE_STRING)
SK_ENUM_H(NodeKind, NODE_KIND); SK_ENUM_H(NodeKind, NODE_KIND);

View File

@ -20,12 +20,9 @@ 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_assert(struct parser* self); struct node* parser_try_assert(struct parser* self);
struct node* parser_try_or(struct parser* self);
struct node* parser_try_and(struct parser* self);
struct node* parser_try_term(struct parser* self); struct node* parser_try_term(struct parser* self);
struct node* parser_try_factor(struct parser* self); struct node* parser_try_factor(struct parser* self);
struct node* parser_try_usub(struct parser* self); struct node* parser_try_usub(struct parser* self);
struct node* parser_try_not(struct parser* self);
struct node* parser_try_pow(struct parser* self); struct node* parser_try_pow(struct parser* self);
struct node* parser_try_literal(struct parser* self); struct node* parser_try_literal(struct parser* self);
struct node* parser_try_builtin(struct parser* self); struct node* parser_try_builtin(struct parser* self);

View File

@ -9,9 +9,7 @@
G(OP_PUSH), \ G(OP_PUSH), \
G(OP_ADD), G(OP_SUB), G(OP_MUL), \ G(OP_ADD), G(OP_SUB), G(OP_MUL), \
G(OP_DIV), G(OP_MOD), G(OP_POW), \ 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_BR), G(OP_BRF)
SK_ENUM_H(Opcode, OPCODE); SK_ENUM_H(Opcode, OPCODE);

View File

@ -44,20 +44,7 @@ struct value* state_try_get_value(struct state* self, SK value);
SK state_pop(struct state* self); SK state_pop(struct state* self);
SK state_push(struct state* self,
TypeKind type,
union val val,
int line);
SK state_push_int(struct state* self, int integer, int line); SK state_push_int(struct state* self, int integer, int line);
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_string(struct state* self, char const* str, int line);
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs);
TypeKind state_type(struct state* self, SK value);
double state_as_real(struct state* self, SK lhs);
int state_line(struct state* self, SK lhs);
SK state_add(struct state* self); SK state_add(struct state* self);
SK state_sub(struct state* self); SK state_sub(struct state* self);
@ -67,8 +54,4 @@ SK state_div(struct state* self);
SK state_mod(struct state* self); SK state_mod(struct state* self);
SK state_pow(struct state* self); SK state_pow(struct state* self);
SK state_and(struct state* self);
SK state_or(struct state* self);
SK state_not(struct state* self);
#endif #endif

View File

@ -9,9 +9,7 @@ G(TOKEN_INT), \
G(TOKEN_ADD), G(TOKEN_SUB), \ G(TOKEN_ADD), G(TOKEN_SUB), \
G(TOKEN_MUL), G(TOKEN_DIV), G(TOKEN_MOD), \ G(TOKEN_MUL), G(TOKEN_DIV), G(TOKEN_MOD), \
G(TOKEN_POW), G(TOKEN_OPAR), G(TOKEN_CPAR), \ G(TOKEN_POW), G(TOKEN_OPAR), G(TOKEN_CPAR), \
G(TOKEN_ASSERT), G(TOKEN_ASSERT_EQ), \ G(TOKEN_ASSERT), G(TOKEN_ASSERT_EQ)
G(TOKEN_BOOL), G(TOKEN_AND), G(TOKEN_OR), \
G(TOKEN_NOT), G(TOKEN_FLOAT), G(TOKEN_STRING)
SK_ENUM_H(TokenKind, TOKEN_KIND); SK_ENUM_H(TokenKind, TOKEN_KIND);

View File

@ -5,17 +5,13 @@
#include "node.h" #include "node.h"
#define TYPE_KIND(G) \ #define TYPE_KIND(G) \
G(TYPE_INT), G(TYPE_BOOL), G(TYPE_FLOAT), \ G(TYPE_INT)
G(TYPE_STRING)
SK_ENUM_H(TypeKind, TYPE_KIND); SK_ENUM_H(TypeKind, TYPE_KIND);
union val union val
{ {
int integer; int integer;
double real;
bool boolean;
char* str;
}; };
struct value struct value

View File

@ -29,51 +29,19 @@ void compiler_compile(struct compiler* self,
} }
} break; } break;
case NODE_NOT: {
compiler_compile_children(self, node, prog);
prog_add_instr(prog, OP_NOT, SK_NO_PARAM);
} break;
case NODE_AND: {
compiler_compile_and(self, node, prog);
} break;
case NODE_OR: {
compiler_compile_or(self, node, prog);
} break;
case NODE_ASSERT_EQ: { case NODE_ASSERT_EQ: {
compiler_compile_children(self, node, prog); compiler_compile_children(self, node, prog);
prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM); prog_add_instr(prog, OP_ASSERT_EQ, SK_NO_PARAM);
} break; } break;
case NODE_BOOL: {
union val val;
val.boolean =
strcmp(node->token->value, "true") == 0;
compiler_compile_value(self, node, prog, TYPE_BOOL,
val);
} break;
case NODE_INT: { case NODE_INT: {
struct value* value = malloc(sizeof(struct value));
union val val; union val val;
val.integer = atoi(node->token->value); val.integer = atoi(node->token->value);
compiler_compile_value(self, node, prog, TYPE_INT, value_init(value, TYPE_INT, val, node->token->line);
val);
} break;
case NODE_FLOAT: { size_t idx = prog_add_constant(prog, value);
union val val; prog_add_instr(prog, OP_PUSH, idx);
val.real = atof(node->token->value);
compiler_compile_value(self, node, prog, TYPE_FLOAT,
val);
} break;
case NODE_STRING: {
union val val;
val.str = strdup(node->token->value);
compiler_compile_value(self, node, prog, TYPE_STRING,
val);
} break; } break;
case NODE_ADD: { case NODE_ADD: {
@ -133,101 +101,3 @@ void compiler_compile_children(struct compiler* self,
compiler_compile(self, child, prog); compiler_compile(self, child, prog);
} }
} }
void compiler_compile_value(struct compiler* self,
struct node* node,
struct prog* prog,
TypeKind type,
union val val)
{
(void) self;
struct value* value = malloc(sizeof(struct value));
value_init(value, type, val, node->token->line);
size_t idx = prog_add_constant(prog, value);
prog_add_instr(prog, OP_PUSH, idx);
}
void compiler_compile_and(struct compiler* self,
struct node* node,
struct prog* prog)
{
assert(self);
assert(node);
assert(prog);
struct vec to_false;
vec_init(&to_false);
for (size_t i =0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to false
vec_push(&to_false, (void*) brf);
}
union val tval;
tval.boolean = true;
compiler_compile_value(self, node, prog, TYPE_BOOL, tval);
size_t to_end = prog_add_instr(prog, OP_BR, 0);
union val fval;
fval.boolean = false;
size_t false_point = prog->opcodes.size;
compiler_compile_value(self, node, prog, TYPE_BOOL, fval);
size_t end_point = prog->opcodes.size;
((size_t*)prog->params.data)[to_end] = end_point;
for (size_t i=0; i<to_false.size; i++)
{
((size_t*)prog->params.data)[(size_t)
to_false.data[i]] = false_point;
}
vec_free(&to_false);
}
void compiler_compile_or(struct compiler* self,
struct node* node,
struct prog* prog)
{
assert(self);
assert(node);
assert(prog);
struct vec to_true;
vec_init(&to_true);
for (size_t i =0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog);
prog_add_instr(prog, OP_NOT, 0);
size_t brf = prog_add_instr(prog, OP_BRF, 0); // to true
vec_push(&to_true, (void*) brf);
}
union val fval;
fval.boolean = false;
compiler_compile_value(self, node, prog, TYPE_BOOL, fval);
size_t to_end = prog_add_instr(prog, OP_BR, 0);
union val tval;
tval.boolean = true;
size_t true_point = prog->opcodes.size;
compiler_compile_value(self, node, prog, TYPE_BOOL, tval);
size_t end_point = prog->opcodes.size;
((size_t*)prog->params.data)[to_end] = end_point;
for (size_t i=0; i<to_true.size; i++)
{
((size_t*)prog->params.data)[(size_t)
to_true.data[i]] = true_point;
}
vec_free(&to_true);
}

View File

@ -73,31 +73,6 @@ void exec_execute(struct exec* self,
constant->line constant->line
); );
} break; } break;
case TYPE_FLOAT: {
state_push_float(
state,
constant->val.real,
constant->line
);
} break;
case TYPE_STRING: {
state_push_string(
state,
constant->val.str,
constant->line
);
} break;
case TYPE_BOOL: {
state_push_bool(
state,
constant->val.boolean,
constant->line
);
} break;
default: { default: {
fprintf(stderr, "cannot push value '%s'\n", fprintf(stderr, "cannot push value '%s'\n",
TypeKindStr[constant->type]); TypeKindStr[constant->type]);
@ -142,41 +117,6 @@ void exec_execute(struct exec* self,
self->pc++; self->pc++;
} break; } break;
case OP_NOT: {
state_not(state);
self->pc++;
} break;
case OP_AND: {
state_and(state);
self->pc++;
} break;
case OP_OR: {
state_or(state);
self->pc++;
} break;
case OP_BR: {
self->pc = param;
} break;
case OP_BRF: {
SK addr = state_pop(state);
bool val =
state_try_get_value(state, addr)->val.boolean;
if (!val)
{
self->pc = param;
}
else
{
self->pc++;
}
} break;
default: { default: {
fprintf(stderr, "cannot execute opcode '%s'\n", fprintf(stderr, "cannot execute opcode '%s'\n",
OpcodeStr[opcode]); OpcodeStr[opcode]);

View File

@ -31,13 +31,6 @@ void lexer_free(struct lexer* self)
} }
} }
bool lexer_is_at_end(struct lexer* self)
{
assert(self);
lexer_skip_comments(self);
return self->context.cursor >= self->len;
}
void lexer_skip_spaces(struct lexer* self) void lexer_skip_spaces(struct lexer* self)
{ {
assert(self); assert(self);
@ -54,25 +47,6 @@ void lexer_skip_spaces(struct lexer* self)
} }
} }
void lexer_skip_comments(struct lexer* self)
{
assert(self);
lexer_skip_spaces(self);
while (self->context.cursor < self->len
&& self->source[self->context.cursor] == '#')
{
while (self->context.cursor < self->len
&& self->source[self->context.cursor] != '\n')
{
self->context.cursor++;
}
lexer_skip_spaces(self);
}
}
bool lexer_is_sep(struct lexer* self, size_t index) bool lexer_is_sep(struct lexer* self, size_t index)
{ {
if (index >= self->len) { return true; } if (index >= self->len) { return true; }
@ -124,29 +98,20 @@ struct token* lexer_try_new_next(struct lexer* self)
{ {
assert(self); assert(self);
lexer_skip_comments(self);
if (!errors_ok()) if (!errors_ok())
{ {
return NULL; return NULL;
} }
struct token* tok = NULL; lexer_skip_spaces(self);
if ( (tok=lexer_try_scan_float(self)) ) struct token* tok = NULL;
{
return tok;
}
if ( (tok=lexer_try_scan_int(self)) ) if ( (tok=lexer_try_scan_int(self)) )
{ {
return tok; return tok;
} }
if ( (tok=lexer_try_scan_string(self)) )
{
return tok;
}
SK_SCAN_TEXT("+", TOKEN_ADD); SK_SCAN_TEXT("+", TOKEN_ADD);
SK_SCAN_TEXT("-", TOKEN_SUB); SK_SCAN_TEXT("-", TOKEN_SUB);
SK_SCAN_TEXT("*", TOKEN_MUL); SK_SCAN_TEXT("*", TOKEN_MUL);
@ -157,12 +122,6 @@ struct token* lexer_try_new_next(struct lexer* self)
SK_SCAN_TEXT(")", TOKEN_CPAR); SK_SCAN_TEXT(")", TOKEN_CPAR);
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("false", TOKEN_BOOL, "false");
SK_SCAN_KEYWORD("and", TOKEN_AND, NULL);
SK_SCAN_KEYWORD("or", TOKEN_OR, NULL);
SK_SCAN_KEYWORD("not", TOKEN_NOT, NULL);
if (self->context.cursor < self->len) if (self->context.cursor < self->len)
{ {
@ -221,142 +180,6 @@ struct token* lexer_try_scan_int(struct lexer* self)
return tok; return tok;
} }
struct token* lexer_try_scan_float(struct lexer* self)
{
assert(self);
size_t cursor = self->context.cursor;
struct str value;
str_init(&value);
if (cursor < self->len
&& self->source[cursor] == '-')
{
str_push(&value, self->source[cursor]);
cursor++;
}
while (cursor < self->len
&& isdigit(self->source[cursor]))
{
str_push(&value, self->source[cursor]);
cursor++;
}
if (cursor >= self->len
|| self->source[cursor] != '.')
{
str_free(&value);
return NULL;
}
str_push(&value, self->source[cursor]);
cursor++;
while (cursor < self->len
&& isdigit(self->source[cursor]))
{
str_push(&value, self->source[cursor]);
cursor++;
}
struct token* tok = NULL;
if (value.size > 0
&& (value.value[0] != '-' || value.size > 1))
{
tok = malloc(sizeof(struct token));
token_init(tok, TOKEN_FLOAT,
value.value, self->context.line);
self->context.cursor = cursor;
}
str_free(&value);
return tok;
}
struct token* lexer_try_scan_string(struct lexer* self)
{
assert(self);
size_t cursor = self->context.cursor;
if (cursor >= self->len
|| self->source[cursor] != '"')
{
return NULL;
}
cursor++;
struct str value;
str_init(&value);
bool escaped = false;
while (cursor < self->len
&& self->source[cursor] != '"')
{
if (self->source[cursor] == '\\')
{
escaped = true;
}
if (escaped)
{
cursor++;
switch (self->source[cursor])
{
case '\\': {
str_push(&value, '\\');
} break;
case 'n': {
str_push(&value, '\n');
} break;
case 'r': {
str_push(&value, '\r');
} break;
case 't': {
str_push(&value, '\t');
} break;
case 'e': {
str_push(&value, '\e');
} break;
case '"': {
str_push(&value, '"');
} break;
default: {
errors_push(self->context.line,
"unknown escape symbol");
str_free(&value);
return NULL;
} break;
}
escaped = false;
cursor++;
continue;
}
str_push(&value, self->source[cursor]);
cursor++;
}
if (cursor >= self->len
|| self->source[cursor] != '"')
{
str_free(&value);
return NULL;
}
cursor++;
struct token* tok = malloc(sizeof(struct token));
token_init(tok, TOKEN_STRING, value.value, self->context.line);
self->context.cursor = cursor;
str_free(&value);
return tok;
}
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

@ -50,40 +50,19 @@ struct node* parser_try_root(struct parser* self)
node_init(node, NODE_ROOT, tok); node_init(node, NODE_ROOT, tok);
struct str error_str; while (true)
str_init(&error_str);
while (!lexer_is_at_end(&self->lexer))
{ {
struct node* expr = SK_TRY(parser_try_expr); struct node* expr = SK_TRY(parser_try_expr);
if (!expr) { break; }
if (!expr)
{
while (self->lexer.context.cursor < self->lexer.len
&& !lexer_is_sep(&self->lexer,
self->lexer.context.cursor))
{
str_push(&error_str,
self->lexer.source[
self->lexer.context.cursor
]);
self->lexer.context.cursor++;
}
break;
}
node_push_new_child(node, expr); node_push_new_child(node, expr);
} }
if (self->lexer.context.cursor < self->lexer.len) if (self->lexer.context.cursor < self->lexer.len)
{ {
errors_push(self->lexer.context.line, errors_push(self->lexer.context.line, "unexpected end");
"unexpected end near '%s'",
error_str.value);
} }
str_free(&error_str);
return node; return node;
} }
@ -94,7 +73,7 @@ struct node* parser_try_expr(struct parser* self)
return SK_TRY(parser_try_assert); return SK_TRY(parser_try_assert);
} }
return SK_TRY(parser_try_or); return SK_TRY(parser_try_term);
} }
struct node* parser_try_assert(struct parser* self) struct node* parser_try_assert(struct parser* self)
@ -109,19 +88,12 @@ struct node* parser_try_assert(struct parser* self)
struct token* tok = lexer_try_new_next(&self->lexer); struct token* tok = lexer_try_new_next(&self->lexer);
struct node* lhs = SK_TRY(parser_try_expr); struct node* lhs = SK_TRY(parser_try_expr);
if (!lhs) if (!lhs) { return NULL; }
{
token_free(tok); free(tok);
return NULL;
}
if (!lexer_next_is(&self->lexer, TOKEN_ASSERT_EQ)) if (!lexer_next_is(&self->lexer, TOKEN_ASSERT_EQ))
{ {
token_free(tok); token_free(tok);
free(tok); free(tok);
node_free(lhs);
free(lhs);
return NULL; return NULL;
} }
@ -131,8 +103,6 @@ struct node* parser_try_assert(struct parser* self)
{ {
token_free(tok); token_free(tok);
free(tok); free(tok);
node_free(lhs);
free(lhs);
return NULL; return NULL;
} }
@ -143,66 +113,6 @@ struct node* parser_try_assert(struct parser* self)
return node; return node;
} }
struct node* parser_try_or(struct parser* self)
{
assert(self);
struct node* lhs = SK_TRY(parser_try_and);
if (!lhs) { return NULL; }
while (lexer_next_is(&self->lexer, TOKEN_OR))
{
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_OR, lexer_try_new_next(
&self->lexer
));
node_push_new_child(node, lhs);
struct node* rhs = SK_TRY(parser_try_and);
if (!rhs)
{
node_free(node);
free(node);
return NULL;
}
node_push_new_child(node, rhs);
lhs = node;
}
return lhs;
}
struct node* parser_try_and(struct parser* self)
{
assert(self);
struct node* lhs = SK_TRY(parser_try_term);
if (!lhs) { return NULL; }
while (lexer_next_is(&self->lexer, TOKEN_AND))
{
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_AND, lexer_try_new_next(
&self->lexer
));
node_push_new_child(node, lhs);
struct node* rhs = SK_TRY(parser_try_term);
if (!rhs)
{
node_free(node);
free(node);
return NULL;
}
node_push_new_child(node, rhs);
lhs = node;
}
return lhs;
}
struct node* parser_try_term(struct parser* self) struct node* parser_try_term(struct parser* self)
{ {
assert(self); assert(self);
@ -315,33 +225,6 @@ struct node* parser_try_usub(struct parser* self)
return node; return node;
} }
return SK_TRY(parser_try_not);
}
struct node* parser_try_not(struct parser* self)
{
assert(self);
if (lexer_next_is(&self->lexer, TOKEN_NOT))
{
struct node* node = malloc(sizeof(struct node));
node_init(node, NODE_NOT, lexer_try_new_next(
&self->lexer
));
struct node* child = SK_TRY(parser_try_not);
if (!child)
{
node_free(node);
free(node);
return NULL;
}
node_push_new_child(node, child);
return node;
}
return SK_TRY(parser_try_pow); return SK_TRY(parser_try_pow);
} }
@ -407,17 +290,6 @@ struct node* parser_try_literal(struct parser* self)
struct node* parser_try_builtin(struct parser* self) struct node* parser_try_builtin(struct parser* self)
{ {
if (lexer_next_is(&self->lexer, TOKEN_BOOL))
{
struct node* node = malloc(sizeof(struct node));
node_init(node,
NODE_BOOL,
lexer_try_new_next(&self->lexer));
return node;
}
if (lexer_next_is(&self->lexer, TOKEN_INT)) if (lexer_next_is(&self->lexer, TOKEN_INT))
{ {
struct node* node = malloc(sizeof(struct node)); struct node* node = malloc(sizeof(struct node));
@ -429,27 +301,5 @@ struct node* parser_try_builtin(struct parser* self)
return node; return node;
} }
if (lexer_next_is(&self->lexer, TOKEN_FLOAT))
{
struct node* node = malloc(sizeof(struct node));
node_init(node,
NODE_FLOAT,
lexer_try_new_next(&self->lexer));
return node;
}
if (lexer_next_is(&self->lexer, TOKEN_STRING))
{
struct node* node = malloc(sizeof(struct node));
node_init(node,
NODE_STRING,
lexer_try_new_next(&self->lexer));
return node;
}
return NULL; return NULL;
} }

View File

@ -107,15 +107,14 @@ SK state_pop(struct state* self)
return value; return value;
} }
SK state_push(struct state* self, SK state_push_int(struct state* self, int integer, int line)
TypeKind type,
union val val,
int line)
{ {
assert(self); assert(self);
struct value* value = malloc(sizeof(struct value)); struct value* value = malloc(sizeof(struct value));
value_init(value, type, val, line); union val val;
val.integer = integer;
value_init(value, TYPE_INT, val, line);
struct frame* frame = state_frame(self); struct frame* frame = state_frame(self);
struct local* local = malloc(sizeof(struct local)); struct local* local = malloc(sizeof(struct local));
@ -128,392 +127,105 @@ SK state_push(struct state* self,
return self->addr - 1; return self->addr - 1;
} }
SK state_push_int(struct state* self, int integer, int line)
{
assert(self);
union val val;
val.integer = integer;
return state_push(self, TYPE_INT, val, line);
}
SK state_push_bool(struct state* self, bool boolean, int line)
{
assert(self);
union val val;
val.boolean = boolean;
return state_push(self, TYPE_BOOL, val, line);
}
SK state_push_float(struct state* self, double real, int line)
{
assert(self);
union val val;
val.real = real;
return state_push(self, TYPE_FLOAT, val ,line);
}
SK state_push_string(struct state* self, char const* str, int line)
{
assert(self);
union val val;
val.str = strdup(str);
return state_push(self, TYPE_STRING, val ,line);
}
TypeKind state_common_num_type(struct state* self, SK lhs, SK rhs)
{
assert(self);
struct value const* left = state_try_get_value(self, lhs);
struct value const* right = state_try_get_value(self, rhs);
if (left->type == TYPE_FLOAT
|| right->type == TYPE_FLOAT)
{
return TYPE_FLOAT;
}
return TYPE_INT;
}
TypeKind state_type(struct state* self, SK value)
{
assert(self);
struct value const* val = state_try_get_value(self, value);
return val->type;
}
double state_as_real(struct state* self, SK lhs)
{
assert(self);
struct value* value = state_try_get_value(self, lhs);
if (value->type == TYPE_INT)
{
return value->val.integer;
}
else if (value->type == TYPE_FLOAT)
{
return value->val.real;
}
errors_push(value->line, "expected a number, got '%s'",
TypeKindStr[value->type] + strlen("TYPE_"));
return 0.0;
}
int state_line(struct state* self, SK lhs)
{
assert(self);
struct value const* value = state_try_get_value(self, lhs);
return value->line;
}
SK state_add(struct state* self) SK state_add(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs);
if(state_type(self, lhs) == TYPE_STRING
&& state_type(self, rhs) == TYPE_STRING)
{
struct value* left = state_try_get_value(self, lhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs); struct value* right = state_try_get_value(self, rhs);
struct str val;
str_init(&val);
str_extend(&val, left->val.str);
str_extend(&val, right->val.str);
SK res = state_push_string(self, val.value, left->line);
str_free(&val);
return res;
}
else if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
state_as_real(self, lhs) + state_as_real(self, rhs), left->val.integer + right->val.integer,
state_line(self, lhs) left->line
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
state_as_real(self, lhs) + state_as_real(self, rhs),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot addition");
return 0;
}
}
SK state_sub(struct state* self) SK state_sub(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
state_as_real(self, lhs) - state_as_real(self, rhs), left->val.integer - right->val.integer,
state_line(self, lhs) left->line
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
state_as_real(self, lhs) - state_as_real(self, rhs),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot substract");
return 0;
}
}
SK state_usub(struct state* self) SK state_usub(struct state* self)
{ {
SK lhs = state_pop(self); SK lhs = state_pop(self);
struct value const* value = state_try_get_value(self, lhs);
TypeKind type = value->type;
if (type == TYPE_INT) struct value* left = state_try_get_value(self, lhs);
{
return state_push_int( return state_push_int(
self, self,
-state_as_real(self, lhs), -left->val.integer,
state_line(self, lhs) left->line
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
-state_as_real(self, lhs),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot apply unary substraction");
return 0;
}
}
SK state_mul(struct state* self) SK state_mul(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
if(state_type(self, lhs) == TYPE_STRING
&& state_type(self, rhs) == TYPE_INT)
{
struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
struct str val;
str_init(&val);
for (int i=0; i<right->val.integer; i++)
{
str_extend(&val, left->val.str);
}
SK res = state_push_string(self, val.value, left->line);
str_free(&val);
return res;
}
else if(state_type(self, lhs) == TYPE_INT
&& state_type(self, rhs) == TYPE_STRING)
{
struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
struct str val;
str_init(&val);
for (int i=0; i<left->val.integer; i++)
{
str_extend(&val, right->val.str);
}
SK res = state_push_string(self, val.value, left->line);
str_free(&val);
return res;
}
else if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
state_as_real(self, lhs) * state_as_real(self, rhs), left->val.integer * right->val.integer,
state_line(self, lhs) left->line
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
state_as_real(self, lhs) * state_as_real(self, rhs),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot multiply");
return 0;
}
}
SK state_div(struct state* self) SK state_div(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
state_as_real(self, lhs) / state_as_real(self, rhs), left->val.integer / right->val.integer,
state_line(self, lhs) left->line
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
state_as_real(self, lhs) / state_as_real(self, rhs),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot divide");
return 0;
}
}
SK state_mod(struct state* self) SK state_mod(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
fmod(state_as_real(self, lhs), fmod(left->val.integer, right->val.integer),
state_as_real(self, rhs)), left->line
state_line(self, lhs)
); );
} }
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
fmod(state_as_real(self, lhs),
state_as_real(self, rhs)),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot apply mod");
return 0;
}
}
SK state_pow(struct state* self) SK state_pow(struct state* self)
{ {
SK rhs = state_pop(self); SK rhs = state_pop(self);
SK lhs = state_pop(self); SK lhs = state_pop(self);
TypeKind type = state_common_num_type(self, lhs, rhs); struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
if (type == TYPE_INT)
{
return state_push_int( return state_push_int(
self, self,
powf(state_as_real(self, lhs), powf(left->val.integer, right->val.integer),
state_as_real(self, rhs)),
state_line(self, lhs)
);
}
else if (type == TYPE_FLOAT)
{
return state_push_float(
self,
powf(state_as_real(self, lhs),
state_as_real(self, rhs)),
state_line(self, lhs)
);
}
else
{
errors_push(state_line(self, lhs),
"cannot apply pow");
return 0;
}
}
SK state_and(struct state* self)
{
SK rhs = state_pop(self);
SK lhs = state_pop(self);
struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
return state_push_bool(
self,
left->val.boolean && right->val.boolean,
left->line
);
}
SK state_or(struct state* self)
{
SK rhs = state_pop(self);
SK lhs = state_pop(self);
struct value* left = state_try_get_value(self, lhs);
struct value* right = state_try_get_value(self, rhs);
return state_push_bool(
self,
left->val.boolean || right->val.boolean,
left->line
);
}
SK state_not(struct state* self)
{
SK lhs = state_pop(self);
struct value* left = state_try_get_value(self, lhs);
return state_push_bool(
self,
!left->val.boolean,
left->line left->line
); );
} }

View File

@ -16,10 +16,6 @@ void value_init(struct value* self,
void value_free(struct value* self) void value_free(struct value* self)
{ {
assert(self); assert(self);
if (self->type == TYPE_STRING)
{
free(self->val.str);
}
} }
bool value_equals(struct value* self, struct value* rhs) bool value_equals(struct value* self, struct value* rhs)
@ -47,22 +43,9 @@ void value_str(struct value* self, struct str* dest)
switch (self->type) switch (self->type)
{ {
case TYPE_STRING: {
str_format(dest, "%s", self->val.str);
} break;
case TYPE_INT: { case TYPE_INT: {
str_format(dest, "%d", self->val.integer); str_format(dest, "%d", self->val.integer);
} break; } break;
case TYPE_FLOAT: {
str_format(dest, "%f", self->val.real);
} break;
case TYPE_BOOL: {
str_format(dest, "%s",
self->val.boolean ? "true" : "false");
} break;
default: { default: {
fprintf(stderr, "cannot get value string of '%s'\n", fprintf(stderr, "cannot get value string of '%s'\n",
TypeKindStr[self->type]); TypeKindStr[self->type]);

View File

@ -16,10 +16,6 @@ static void test_lexer(char const* source, int count, ...)
for (int i=0; i<count; i++) for (int i=0; i<count; i++)
{ {
struct token* tok = lexer_try_new_next(&lexer); struct token* tok = lexer_try_new_next(&lexer);
if (tok == NULL)
{
fprintf(stderr, "%s == NULL\n", source);
}
CU_ASSERT_FATAL(tok != NULL); CU_ASSERT_FATAL(tok != NULL);
struct str tok_str; struct str tok_str;
str_init(&tok_str); str_init(&tok_str);
@ -30,7 +26,7 @@ static void test_lexer(char const* source, int count, ...)
fprintf(stderr, "%s != %s\n", oracle, tok_str.value); fprintf(stderr, "%s != %s\n", oracle, tok_str.value);
} }
CU_ASSERT_STRING_EQUAL_FATAL(tok_str.value, oracle); CU_ASSERT_STRING_EQUAL(tok_str.value, oracle);
str_free(&tok_str); str_free(&tok_str);
token_free(tok); token_free(tok);
free(tok); free(tok);
@ -64,46 +60,11 @@ static void test_lexer_assert()
); );
} }
static void test_lexer_bool()
{
test_lexer("true false and or not", 5,
"BOOL[true]",
"BOOL[false]",
"AND",
"OR",
"NOT"
);
}
static void test_lexer_float()
{
test_lexer(".4 7. 2.3 -6.12", 4,
"FLOAT[.4]",
"FLOAT[7.]",
"FLOAT[2.3]",
"FLOAT[-6.12]"
);
}
static void test_lexer_string()
{
test_lexer("\" hello \" \"\\\"world\\\"\"", 2,
"STRING[ hello ]",
"STRING[\"world\"]"
);
test_lexer("\"\\n\\r\\t\\e\"", 1,
"STRING[\n\r\t\e]"
);
}
void register_lexer() void register_lexer()
{ {
CU_pSuite suite = CU_add_suite("Lexer", 0, 0); CU_pSuite suite = CU_add_suite("Lexer", 0, 0);
CU_add_test(suite, "Integers", test_lexer_int); CU_add_test(suite, "Integers", test_lexer_int);
CU_add_test(suite, "Assertions", test_lexer_assert); CU_add_test(suite, "Assertions", test_lexer_assert);
CU_add_test(suite, "Booleans", test_lexer_bool);
CU_add_test(suite, "Floats", test_lexer_float);
CU_add_test(suite, "Strings", test_lexer_string);
} }
#endif #endif

View File

@ -48,36 +48,11 @@ static void test_parser_assert()
" assert 32 eq 12 "); " assert 32 eq 12 ");
} }
static void test_parser_bool()
{
test_parser("ROOT(BOOL[true])",
"true");
test_parser("ROOT(NOT(BOOL[false]))",
"not false");
test_parser("ROOT(OR(AND(NOT(BOOL[false]),BOOL[true]),"
"BOOL[false]))",
"not false and true or false");
test_parser("ROOT(AND(NOT(BOOL[false]),OR(BOOL[true],"
"BOOL[false])))",
"not false and (true or false)");
}
static void test_parser_string()
{
test_parser("ROOT(STRING[ok pizza NOW])",
"\"ok pizza NOW\"");
}
void register_parser() void register_parser()
{ {
CU_pSuite suite = CU_add_suite("Parser", 0, 0); CU_pSuite suite = CU_add_suite("Parser", 0, 0);
CU_add_test(suite, "Integers", test_parser_int); CU_add_test(suite, "Integers", test_parser_int);
CU_add_test(suite, "Assertions", test_parser_assert); CU_add_test(suite, "Assertions", test_parser_assert);
CU_add_test(suite, "Booleans", test_parser_bool);
CU_add_test(suite, "Strings", test_parser_string);
} }
#endif #endif