ADD/ comparisons operators for integers and floats.

main
bog 2023-08-25 11:22:29 +02:00
parent 9ca893dff5
commit 299c095af4
10 changed files with 434 additions and 9 deletions

View File

@ -158,6 +158,94 @@ void compile_node(compiler* self, node* root, program* prog)
compile_children(self, root, prog);
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,
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,
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,
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,
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)
{
compile_number(self, root, prog, OP_IUADD, OP_FUADD);

View File

@ -145,8 +145,13 @@ type* cstatic_resolve_new(cstatic* self, node* ast)
}
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_NE)
{
return cstatic_new_type(self, TY_BOOLEAN);
}
@ -458,6 +463,36 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
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],
msg,
size);
if (!status)
{
return status;
}
status = cstatic_check_type_base(self,
ast->children.data[0],
msg,
size,
TY_INTEGER,
TY_FLOAT,
TYPE_END);
if (!status)
{
return status;
}
}
return 1;
}

View File

@ -26,6 +26,8 @@ TYPE (int|float|bool|str|array)
}
"assert" { return ASSERT; }
"<=" { return LE; }
">=" { return GE; }
"<" { return LT; }
">" { return GT; }
"," { return COMMA; }

View File

@ -10,7 +10,8 @@
G(NODE_ASSERT), \
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_ARRAY), G(NODE_INDEX)
G(NODE_ARRAY), G(NODE_INDEX), G(NODE_LT), G(NODE_LE), \
G(NODE_GT), G(NODE_GE)
#include "mutils.h"

View File

@ -33,7 +33,15 @@
G(OP_ACAT), \
G(OP_AMUL), \
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) \
enum Opcodes {
OPCODES(GEN_ENUM)

View File

@ -22,15 +22,14 @@
};
%left ASSERT
%token LT GT
%token <str> TYPE BOOLEAN INTEGER FLOAT STRING
%type <n_children> expr exprs prog array builtins
%type <n_children> expr_list type type_list
%left EQ NE
%left LT GT LE GE
%left AND
%left OR
%left ADD
%left SUB
%left ADD SUB
%left MUL DIV MOD
%left POW
%left NOT
@ -118,7 +117,47 @@ expr:
}
| expr_unop {}
| 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));
@ -243,6 +282,7 @@ expr:
$$ = $2;
}
| expr_unop {}
;
@ -265,8 +305,8 @@ expr_unop:
;
type_list:
expr { $$ = $1; }
| type_list COMMA expr { $$ = $1 + $3; }
type { $$ = $1; }
| type_list COMMA type { $$ = $1 + $3; }
;
@ -299,6 +339,28 @@ type:
stack_push(n);
$$ = 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;
}
;
builtins:

162
src/vm.c
View File

@ -76,6 +76,16 @@ void vm_exec(vm* self, program* prog)
case OP_TMUL: vm_tmul(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;
default: {
fprintf(stderr, "unknown opcode %s\n",
OpcodesStr[opcode]);
@ -740,3 +750,155 @@ void vm_tadd(vm* self)
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++;
}

View File

@ -60,4 +60,14 @@ void vm_amul(vm* self);
void vm_tmul(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);
#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

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