Compare commits

..

No commits in common. "4f6f3253c251e69aaacb88fcc0290aca5387a037" and "bd84f3bb3ded021898c908f0a701cd9d23d1f5ba" have entirely different histories.

17 changed files with 21 additions and 459 deletions

View File

@ -4,13 +4,7 @@ EXPR ::=
| EQNE | EQNE
ASSERT ::= assert EXPR ASSERT ::= assert EXPR
EQNE ::= EQNE ::=
| CMP | BUILTIN
| CMP eq CMP | BUILTIN eq BUILTIN
| CMP ne CMP | BUILTIN ne BUILTIN
CMP ::= TERM ((lt | le | ge | gt) TERM)?
TERM ::= FACTOR ((add | sub) FACTOR)*
FACTOR ::= POWER ((mul | div | mod) POWER)*
POWER ::= UNARY (pow UNARY)?
UNARY ::= sub? GROUP
GROUP ::= BUILTIN | opar EXPR cpar
BUILTIN ::= num | bool | str BUILTIN ::= num | bool | str

View File

@ -1,7 +1,6 @@
#ifndef RZ_COMMONS_H #ifndef RZ_COMMONS_H
#define RZ_COMMONS_H #define RZ_COMMONS_H
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>

View File

@ -77,67 +77,6 @@ void compiler_run(compiler_t* compiler, node_t* node)
node->type == NODE_EQ ? OP_EQ : OP_NE, RZ_NO_PARAM); node->type == NODE_EQ ? OP_EQ : OP_NE, RZ_NO_PARAM);
} break; } break;
case NODE_LT:
case NODE_LE:
case NODE_GT:
case NODE_GE: {
assert(node->children.size == 2);
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, node_child(node, i));
}
Opcode op;
switch (node->type)
{
case NODE_LT: op = OP_LT; break;
case NODE_LE: op = OP_LE; break;
case NODE_GT: op = OP_GT; break;
case NODE_GE: op = OP_GE; break;
default: assert(0);
}
mod_push_instr(compiler->mod, op, RZ_NO_PARAM);
} break;
case NODE_ADD:
case NODE_SUB:
case NODE_MUL:
case NODE_DIV:
case NODE_MODULO:
case NODE_POW: {
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, node_child(node, i));
}
Opcode op;
if (node->type == NODE_SUB
&& node->children.size == 1)
{
op = OP_USUB;
}
else
{
switch (node->type)
{
case NODE_ADD: op = OP_ADD; break;
case NODE_SUB: op = OP_SUB; break;
case NODE_MUL: op = OP_MUL; break;
case NODE_DIV: op = OP_DIV; break;
case NODE_MODULO: op = OP_MODULO; break;
case NODE_POW: op = OP_POW; break;
default: assert(0);
}
}
mod_push_instr(compiler->mod, op, RZ_NO_PARAM);
} break;
default: { default: {
fprintf(stderr, "Cannot compile unknown node '%s'", fprintf(stderr, "Cannot compile unknown node '%s'",
NodeTypeStr[node->type]); NodeTypeStr[node->type]);

View File

@ -36,37 +36,10 @@ node_t* lexer_try_new_next(lexer_t* lexer)
lexer_skip_spaces(lexer); lexer_skip_spaces(lexer);
// Comments
// ========
while (lexer->cursor < len
&& lexer->source[lexer->cursor] == '#')
{
while (lexer->cursor < len
&& lexer->source[lexer->cursor] != '\n')
{
lexer->cursor++;
}
lexer_skip_spaces(lexer);
}
// Text // Text
// ==== // ====
RZ_TEXT("(", NODE_OPAR, 0);
RZ_TEXT(")", NODE_CPAR, 0);
RZ_TEXT("+", NODE_ADD, 0);
RZ_TEXT("*", NODE_MUL, 0);
RZ_TEXT("/", NODE_DIV, 0);
RZ_TEXT("%", NODE_MODULO, 0);
RZ_TEXT("^", NODE_POW, 0);
RZ_TEXT("==", NODE_EQ, 0); RZ_TEXT("==", NODE_EQ, 0);
RZ_TEXT("!=", NODE_NE, 0); RZ_TEXT("!=", NODE_NE, 0);
RZ_TEXT("<=", NODE_LE, 0);
RZ_TEXT(">=", NODE_GE, 0);
RZ_TEXT("<", NODE_LT, 0);
RZ_TEXT(">", NODE_GT, 0);
// Keywords // Keywords
// ======== // ========
@ -119,9 +92,7 @@ node_t* lexer_try_new_next(lexer_t* lexer)
} }
if (res_str.size > 0 if (res_str.size > 0
&& res_str.data[res_str.size - 1] != '-' && (cursor >= len || isspace(lexer->source[cursor])))
&& (cursor >= len || !(isalnum(lexer->source[cursor])
|| lexer->source[cursor] == '.')))
{ {
node_t* tok = malloc(sizeof(node_t)); node_t* tok = malloc(sizeof(node_t));
node_init(tok, NODE_NUM, res_str.data, lexer->line); node_init(tok, NODE_NUM, res_str.data, lexer->line);
@ -136,8 +107,6 @@ node_t* lexer_try_new_next(lexer_t* lexer)
str_free(&res_str); str_free(&res_str);
} }
RZ_TEXT("-", NODE_SUB, 0);
if (lexer->cursor < len && lexer->err) if (lexer->cursor < len && lexer->err)
{ {
size_t const SZ = RZ_STR_LIMIT; size_t const SZ = RZ_STR_LIMIT;
@ -197,14 +166,6 @@ void lexer_skip_spaces(lexer_t* lexer)
} }
void lexer_skip_next(lexer_t* lexer)
{
assert(lexer);
node_t* node = lexer_try_new_next(lexer);
node_free(node);
free(node);
}
node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw, node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw,
NodeType type, int has_value, NodeType type, int has_value,
int is_kw) int is_kw)
@ -340,13 +301,6 @@ int lexer_is_sep(lexer_t* lexer, size_t idx)
return 1; return 1;
} }
return return c == '='
c == '='
|| c == '+'
|| c == '-'
|| c == '*'
|| c == '/'
|| c == '%'
|| c == '^'
|| c == '!'; || c == '!';
} }

View File

@ -18,7 +18,6 @@ void lexer_free(lexer_t* lexer);
node_t* lexer_try_new_next(lexer_t* lexer); node_t* lexer_try_new_next(lexer_t* lexer);
NodeType lexer_peek(lexer_t* lexer, int lookahead); NodeType lexer_peek(lexer_t* lexer, int lookahead);
void lexer_skip_spaces(lexer_t* lexer); void lexer_skip_spaces(lexer_t* lexer);
void lexer_skip_next(lexer_t* lexer);
node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw, node_t* lexer_try_new_keyword(lexer_t* lexer, char* kw,
NodeType type, int has_value, NodeType type, int has_value,

View File

@ -7,10 +7,7 @@
G(NODE_MOD), \ G(NODE_MOD), \
G(NODE_NUM), G(NODE_BOOL), G(NODE_STR), \ G(NODE_NUM), G(NODE_BOOL), G(NODE_STR), \
G(NODE_ASSERT), \ G(NODE_ASSERT), \
G(NODE_EQ), G(NODE_NE), \ G(NODE_EQ), G(NODE_NE)
G(NODE_LT), G(NODE_LE), G(NODE_GT), G(NODE_GE), \
G(NODE_ADD), G(NODE_SUB), G(NODE_MUL), G(NODE_DIV), \
G(NODE_MODULO), G(NODE_POW), G(NODE_OPAR), G(NODE_CPAR)
RZ_ENUM_H(NodeType, NODE_TYPE); RZ_ENUM_H(NodeType, NODE_TYPE);

View File

@ -6,10 +6,7 @@
#define OPCODES(G) \ #define OPCODES(G) \
G(OP_ASSERT), \ G(OP_ASSERT), \
G(OP_PUSH), G(OP_POP), \ G(OP_PUSH), G(OP_POP), \
G(OP_EQ), G(OP_NE), \ G(OP_EQ), G(OP_NE)
G(OP_LT), G(OP_LE), G(OP_GT), G(OP_GE), \
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), \
G(OP_MODULO), G(OP_POW), G(OP_USUB)
RZ_ENUM_H(Opcode, OPCODES); RZ_ENUM_H(Opcode, OPCODES);

View File

@ -80,7 +80,7 @@ node_t* parser_try_new_assert(parser_t* parser)
node_t* parser_try_new_eqne(parser_t* parser) node_t* parser_try_new_eqne(parser_t* parser)
{ {
assert(parser); assert(parser);
node_t* lhs = parser_try_new_cmp(parser); node_t* lhs = parser_try_new_builtin(parser);
while (1) while (1)
{ {
@ -91,7 +91,7 @@ node_t* parser_try_new_eqne(parser_t* parser)
node_t* node = lexer_try_new_next(parser->lexer); node_t* node = lexer_try_new_next(parser->lexer);
node_add_new_child(node, lhs); node_add_new_child(node, lhs);
node_add_new_child(node, parser_try_new_cmp(parser)); node_add_new_child(node, parser_try_new_builtin(parser));
lhs = node; lhs = node;
} }
@ -104,132 +104,6 @@ node_t* parser_try_new_eqne(parser_t* parser)
return lhs; return lhs;
} }
node_t* parser_try_new_cmp(parser_t* parser)
{
assert(parser);
node_t* lhs = parser_try_new_term(parser);
int next = lexer_peek(parser->lexer, 1);
if (next == NODE_LT
|| next == NODE_GT
|| next == NODE_LE
|| next == NODE_GE)
{
node_t* node = parser_try_new_consume(parser, next);
node_add_new_child(node, lhs);
node_add_new_child(node, parser_try_new_term(parser));
lhs = node;
}
return lhs;
}
node_t* parser_try_new_term(parser_t* parser)
{
assert(parser);
node_t* lhs = parser_try_new_factor(parser);
while (1)
{
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_ADD
|| next == NODE_SUB)
{
node_t* node = parser_try_new_consume(parser, next);
node_add_new_child(node, lhs);
node_add_new_child(node, parser_try_new_factor(parser));
lhs = node;
}
else
{
break;
}
}
return lhs;
}
node_t* parser_try_new_factor(parser_t* parser)
{
assert(parser);
node_t* lhs = parser_try_new_power(parser);
while (1)
{
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_MUL
|| next == NODE_DIV
|| next == NODE_MODULO)
{
node_t* node = parser_try_new_consume(parser, next);
node_add_new_child(node, lhs);
node_add_new_child(node, parser_try_new_power(parser));
lhs = node;
}
else
{
break;
}
}
return lhs;
}
node_t* parser_try_new_power(parser_t* parser)
{
assert(parser);
node_t* lhs = parser_try_new_unary(parser);
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_POW)
{
node_t* node = parser_try_new_consume(parser, next);
node_add_new_child(node, lhs);
node_add_new_child(node, parser_try_new_unary(parser));
lhs = node;
}
return lhs;
}
node_t* parser_try_new_unary(parser_t* parser)
{
assert(parser);
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_SUB)
{
node_t* node = parser_try_new_consume(parser, next);
node_add_new_child(node, parser_try_new_group(parser));
return node;
}
return parser_try_new_group(parser);
}
node_t* parser_try_new_group(parser_t* parser)
{
assert(parser);
NodeType next = lexer_peek(parser->lexer, 1);
if (next == NODE_OPAR)
{
lexer_skip_next(parser->lexer);
node_t* node = parser_try_new_expr(parser);
lexer_skip_next(parser->lexer);
return node;
}
return parser_try_new_builtin(parser);
}
node_t* parser_try_new_builtin(parser_t* parser) node_t* parser_try_new_builtin(parser_t* parser)
{ {
assert(parser); assert(parser);

View File

@ -18,12 +18,6 @@ node_t* parser_try_new_mod(parser_t* parser);
node_t* parser_try_new_expr(parser_t* parser); node_t* parser_try_new_expr(parser_t* parser);
node_t* parser_try_new_assert(parser_t* parser); node_t* parser_try_new_assert(parser_t* parser);
node_t* parser_try_new_eqne(parser_t* parser); node_t* parser_try_new_eqne(parser_t* parser);
node_t* parser_try_new_cmp(parser_t* parser);
node_t* parser_try_new_term(parser_t* parser);
node_t* parser_try_new_factor(parser_t* parser);
node_t* parser_try_new_power(parser_t* parser);
node_t* parser_try_new_unary(parser_t* parser);
node_t* parser_try_new_group(parser_t* parser);
node_t* parser_try_new_builtin(parser_t* parser); node_t* parser_try_new_builtin(parser_t* parser);
node_t* parser_try_new_consume(parser_t* parser, NodeType type); node_t* parser_try_new_consume(parser_t* parser, NodeType type);

View File

@ -26,18 +26,7 @@ void prepass_run(prepass_t* prepass, node_t* node)
case NODE_BOOL: case NODE_BOOL:
case NODE_ASSERT: case NODE_ASSERT:
case NODE_EQ: case NODE_EQ:
case NODE_NE: case NODE_NE: {
case NODE_LT:
case NODE_LE:
case NODE_GT:
case NODE_GE:
case NODE_ADD:
case NODE_SUB:
case NODE_MUL:
case NODE_DIV:
case NODE_MODULO:
case NODE_POW:{
for (size_t i=0; i<node->children.size; i++) for (size_t i=0; i<node->children.size; i++)
{ {
prepass_run(prepass, (node_t*) node->children.data[i]); prepass_run(prepass, (node_t*) node->children.data[i]);

106
lib/vm.c
View File

@ -2,7 +2,6 @@
#include "lib/commons.h" #include "lib/commons.h"
#include "lib/mod.h" #include "lib/mod.h"
#include "lib/type.h" #include "lib/type.h"
#include "lib/tysy.h"
void vm_init(vm_t* vm, tysy_t* tysy, err_t* err) void vm_init(vm_t* vm, tysy_t* tysy, err_t* err)
{ {
@ -110,7 +109,12 @@ int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param)
if (value->type->kind != TYPE_BOOL) if (value->type->kind != TYPE_BOOL)
{ {
vm_ensure_type(vm, value, TYPE_BOOL); char msg[RZ_STR_LIMIT];
snprintf(msg, RZ_STR_LIMIT,
"type mismatch: BOOL expected, got %s.",
TypeKindStr[value->type->kind] + strlen("TYPE_"));
err_fatal(vm->err, msg, value->line);
vm->pc++; vm->pc++;
break; break;
@ -148,85 +152,6 @@ int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param)
vm_push_value(vm, mod, res); vm_push_value(vm, mod, res);
vm->pc++;
} break;
case OP_LT:
case OP_LE:
case OP_GT:
case OP_GE: {
int r = vm_pop(vm);
int l = vm_pop(vm);
value_t* lhs = mod->values.data[l];
value_t* rhs = mod->values.data[r];
vm_ensure_type(vm, lhs, TYPE_NUM);
vm_ensure_type(vm, rhs, TYPE_NUM);
int val = 0;
switch (op)
{
case OP_LT: val = lhs->value.num < rhs->value.num; break;
case OP_LE: val = lhs->value.num <= rhs->value.num; break;
case OP_GT: val = lhs->value.num > rhs->value.num; break;
case OP_GE: val = lhs->value.num >= rhs->value.num; break;
default: break;
}
value_t* res = tysy_new_bool(vm->tysy, val, lhs->line);
vm_push_value(vm, mod, res);
vm->pc++;
} break;
case OP_ADD:
case OP_SUB:
case OP_MUL:
case OP_DIV:
case OP_MODULO:
case OP_POW: {
int r = vm_pop(vm);
int l = vm_pop(vm);
value_t* lhs = mod->values.data[l];
value_t* rhs = mod->values.data[r];
vm_ensure_type(vm, lhs, TYPE_NUM);
vm_ensure_type(vm, rhs, TYPE_NUM);
double val = 0;
switch (op)
{
case OP_ADD: val = lhs->value.num + rhs->value.num; break;
case OP_SUB: val = lhs->value.num - rhs->value.num; break;
case OP_MUL: val = lhs->value.num * rhs->value.num; break;
case OP_DIV: val = lhs->value.num / rhs->value.num; break;
case OP_MODULO: val = fmod(lhs->value.num, rhs->value.num); break;
case OP_POW: val = powf(lhs->value.num, rhs->value.num); break;
default: assert(0); break;
}
value_t* res = tysy_new_num(vm->tysy, val, lhs->line);
vm_push_value(vm, mod, res);
vm->pc++;
} break;
case OP_USUB: {
int l = vm_pop(vm);
value_t* lhs = mod->values.data[l];
vm_ensure_type(vm, lhs, TYPE_NUM);
double val = -lhs->value.num;
value_t* res = tysy_new_num(vm->tysy, val, lhs->line);
vm_push_value(vm, mod, res);
vm->pc++; vm->pc++;
} break; } break;
@ -239,22 +164,3 @@ int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param)
return 0; return 0;
} }
void vm_ensure_type(vm_t* vm, value_t* value, TypeKind want)
{
assert(vm);
assert(value);
TypeKind got = value->type->kind;
int line = value->line;
if (got != want)
{
char msg[RZ_STR_LIMIT];
snprintf(msg, RZ_STR_LIMIT,
"type mismatch: %s expected, got %s.",
TypeKindStr[want] + strlen("TYPE_"),
TypeKindStr[got] + strlen("TYPE_"));
err_fatal(vm->err, msg, line);
}
}

View File

@ -28,6 +28,5 @@ size_t vm_stack_str(vm_t* vm, char* buffer, size_t size);
int vm_exec_mod(vm_t* vm, mod_t* mod); int vm_exec_mod(vm_t* vm, mod_t* mod);
int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param); int vm_exec_instr(vm_t* vm, mod_t* mod, Opcode op, param_t param);
void vm_ensure_type(vm_t* vm, value_t* value, TypeKind want);
#endif #endif

View File

@ -4,9 +4,6 @@ project(
version: '0.0.0' version: '0.0.0'
) )
cc = meson.get_compiler('c')
m_dep = cc.find_library('m', required: true)
conf = configuration_data() conf = configuration_data()
conf.set('version', meson.project_version()) conf.set('version', meson.project_version())
@ -42,10 +39,6 @@ roza_lib = static_library(
# exec # exec
'lib/vm.c', 'lib/vm.c',
],
dependencies: [
m_dep
] ]
) )

View File

@ -1,34 +1,13 @@
# Equality
# ========
# for num
assert 5 == 5 assert 5 == 5
assert 3 != 5 assert 3 != 5
# for bool
assert true == true assert true == true
assert false == false assert false == false
assert false != true assert false != true
# for str
assert "hello" == "hello" assert "hello" == "hello"
assert "world" != "hello" assert "world" != "hello"
# different types
assert 7 != "hello" assert 7 != "hello"
assert false != 23 assert false != 23
assert "bim" != true assert "bim" != true
# binary comparison operators
assert 3 < 5 == true
assert 5 < 5 == false
assert 7 < 5 == false
assert 3 <= 5 == true
assert 5 <= 5 == true
assert 7 <= 5 == false
assert 3 > 5 == false
assert 5 > 5 == false
assert 7 > 5 == true
assert 3 >= 5 == false
assert 5 >= 5 == true
assert 7 >= 5 == true

View File

@ -1,15 +0,0 @@
# Num Arithmetic
# ==============
assert 5 + 2 == 7
assert 5 - 2 == 3
assert 2 - 5 == -3
assert - 32 == -32
assert 6 * 7 == 42
assert 12 / 4 == 3
assert 5 / 2 == 2.5
assert 35 % 8 == 3
assert 2^6 == 64
assert 1 + 2 * 3 == 7
assert (1 + 2) * 3 == 9
assert 5 == (3 + 2)

View File

@ -77,7 +77,7 @@ Test(lexer, num) {
"NUM[4.1]", "NUM[4.1]",
"NUM[6]"); "NUM[6]");
test_lexer_ko("3..14"); test_lexer_ko("-3..14");
test_lexer_ko("..2"); test_lexer_ko("..2");
test_lexer_ko("2.."); test_lexer_ko("2..");
} }
@ -124,25 +124,4 @@ Test(lexer, cmp) {
"BOOL[false]", "BOOL[false]",
"NE", "NE",
"BOOL[true]"); "BOOL[true]");
test_lexer("1< <= > >=5", 6,
"NUM[1]",
"LT",
"LE",
"GT",
"GE",
"NUM[5]");
}
Test(lexer, num_arith) {
test_lexer("()+-*/^%", 8,
"OPAR",
"CPAR",
"ADD",
"SUB",
"MUL",
"DIV",
"POW",
"MODULO");
} }

View File

@ -76,18 +76,3 @@ Test(parser, eqne) {
test_parser_ok("MOD(EQ(NUM[3],NUM[3]))", " 3 == 3 "); test_parser_ok("MOD(EQ(NUM[3],NUM[3]))", " 3 == 3 ");
test_parser_ok("MOD(NE(NUM[3],NUM[3]))", " 3 != 3 "); test_parser_ok("MOD(NE(NUM[3],NUM[3]))", " 3 != 3 ");
} }
Test(parser, cmp) {
test_parser_ok("MOD(LT(NUM[3],NUM[3]))", " 3 < 3 ");
test_parser_ok("MOD(LE(NUM[3],NUM[3]))", " 3 <= 3 ");
test_parser_ok("MOD(GT(NUM[3],NUM[3]))", " 3 > 3 ");
test_parser_ok("MOD(GE(NUM[3],NUM[3]))", " 3 >= 3 ");
}
Test(parser, num_arith) {
test_parser_ok("MOD(ADD(NUM[1],MUL(NUM[2],NUM[3])))", " 1 + 2 * 3 ");
test_parser_ok("MOD(MUL(ADD(NUM[1],NUM[2]),NUM[3]))", " (1 + 2) * 3 ");
test_parser_ok("MOD(SUB(NUM[1],DIV(NUM[2],NUM[3])))", " 1 - 2 / 3 ");
test_parser_ok("MOD(DIV(SUB(NUM[1],NUM[2]),NUM[3]))", " (1 - 2) / 3 ");
test_parser_ok("MOD(POW(NUM[2],ADD(NUM[1],NUM[2])))", " 2^(1+2) ");
}