ADD: float numbers.
parent
32c0bb8352
commit
2daf39240a
|
@ -1,6 +1,7 @@
|
||||||
#ifndef COMMONS_H
|
#ifndef COMMONS_H
|
||||||
#define COMMON_H
|
#define COMMON_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
#include "cstatic.h"
|
||||||
|
|
||||||
void compiler_init(compiler* self)
|
void compiler_init(compiler* self)
|
||||||
{
|
{
|
||||||
|
@ -26,6 +27,16 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
program_add_instr(prog, OP_PUSH, idx);
|
program_add_instr(prog, OP_PUSH, idx);
|
||||||
value_free(&val);
|
value_free(&val);
|
||||||
}
|
}
|
||||||
|
else if (root->type == NODE_FLOAT)
|
||||||
|
{
|
||||||
|
value val;
|
||||||
|
value_init_float(&val,
|
||||||
|
atof(root->value),
|
||||||
|
root->lineno);
|
||||||
|
size_t idx = program_add_pool(prog, &val);
|
||||||
|
program_add_instr(prog, OP_PUSH, idx);
|
||||||
|
value_free(&val);
|
||||||
|
}
|
||||||
else if (root->type == NODE_INTEGER)
|
else if (root->type == NODE_INTEGER)
|
||||||
{
|
{
|
||||||
value val;
|
value val;
|
||||||
|
@ -43,43 +54,35 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_UADD)
|
else if (root->type == NODE_UADD)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IUADD, OP_FUADD);
|
||||||
program_add_instr(prog, OP_IUADD, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_USUB)
|
else if (root->type == NODE_USUB)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IUSUB, OP_FUSUB);
|
||||||
program_add_instr(prog, OP_IUSUB, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_ADD)
|
else if (root->type == NODE_ADD)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IADD, OP_FADD);
|
||||||
program_add_instr(prog, OP_IADD, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_SUB)
|
else if (root->type == NODE_SUB)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_ISUB, OP_FSUB);
|
||||||
program_add_instr(prog, OP_ISUB, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_MUL)
|
else if (root->type == NODE_MUL)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IMUL, OP_FMUL);
|
||||||
program_add_instr(prog, OP_IMUL, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_DIV)
|
else if (root->type == NODE_DIV)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IDIV, OP_FDIV);
|
||||||
program_add_instr(prog, OP_IDIV, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_MOD)
|
else if (root->type == NODE_MOD)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IMOD, OP_FMOD);
|
||||||
program_add_instr(prog, OP_IMOD, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_POW)
|
else if (root->type == NODE_POW)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_number(self, root, prog, OP_IPOW, OP_FPOW);
|
||||||
program_add_instr(prog, OP_IPOW, NO_PARAM);
|
|
||||||
}
|
}
|
||||||
else if (root->type == NODE_EQ)
|
else if (root->type == NODE_EQ)
|
||||||
{
|
{
|
||||||
|
@ -124,3 +127,35 @@ void compile_children(compiler* self, node* root, program* prog)
|
||||||
compile_node(self, root->children.data[i], prog);
|
compile_node(self, root->children.data[i], prog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compile_number(compiler* self, node* root, program* prog,
|
||||||
|
int integer_op,
|
||||||
|
int float_op)
|
||||||
|
{
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
|
||||||
|
cstatic cs;
|
||||||
|
cstatic_init(&cs);
|
||||||
|
|
||||||
|
int ty = cstatic_resolve(&cs, root);
|
||||||
|
|
||||||
|
switch (ty)
|
||||||
|
{
|
||||||
|
case TY_INTEGER:
|
||||||
|
program_add_instr(prog, integer_op, NO_PARAM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TY_FLOAT:
|
||||||
|
program_add_instr(prog, float_op, NO_PARAM);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "E(%d): cannot add type '%s'.",
|
||||||
|
root->lineno,
|
||||||
|
TypesStr[ty]);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cstatic_free(&cs);
|
||||||
|
}
|
||||||
|
|
|
@ -15,4 +15,7 @@ void compiler_free(compiler* self);
|
||||||
void compile_node(compiler* self, node* root, program* prog);
|
void compile_node(compiler* self, node* root, program* prog);
|
||||||
void compile_children(compiler* self, node* root, program* prog);
|
void compile_children(compiler* self, node* root, program* prog);
|
||||||
|
|
||||||
|
void compile_number(compiler* self, node* root, program* prog,
|
||||||
|
int integer_op,
|
||||||
|
int float_op);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,6 +20,10 @@ int cstatic_resolve(cstatic* self, node* ast)
|
||||||
{
|
{
|
||||||
return TY_INTEGER;
|
return TY_INTEGER;
|
||||||
}
|
}
|
||||||
|
else if (ast->type == NODE_FLOAT)
|
||||||
|
{
|
||||||
|
return TY_FLOAT;
|
||||||
|
}
|
||||||
else if (ast->type == NODE_BOOLEAN
|
else if (ast->type == NODE_BOOLEAN
|
||||||
|| ast->type == NODE_EQ
|
|| ast->type == NODE_EQ
|
||||||
|| ast->type == NODE_NE)
|
|| ast->type == NODE_NE)
|
||||||
|
@ -82,9 +86,10 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
{
|
{
|
||||||
int status = cstatic_check_type(self,
|
int status = cstatic_check_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
TY_BOOLEAN,
|
|
||||||
msg,
|
msg,
|
||||||
size);
|
size,
|
||||||
|
TY_BOOLEAN,
|
||||||
|
TYPE_END);
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
|
@ -109,9 +114,10 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
status = cstatic_check_type(self,
|
status = cstatic_check_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
TY_BOOLEAN,
|
|
||||||
msg,
|
msg,
|
||||||
size);
|
size,
|
||||||
|
TY_BOOLEAN,
|
||||||
|
TYPE_END);
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
|
@ -124,9 +130,11 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
{
|
{
|
||||||
int status = cstatic_check_type(self,
|
int status = cstatic_check_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
TY_INTEGER,
|
|
||||||
msg,
|
msg,
|
||||||
size);
|
size,
|
||||||
|
TY_INTEGER,
|
||||||
|
TY_FLOAT,
|
||||||
|
TYPE_END);
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
|
@ -155,9 +163,11 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
|
|
||||||
status = cstatic_check_type(self,
|
status = cstatic_check_type(self,
|
||||||
ast->children.data[0],
|
ast->children.data[0],
|
||||||
TY_INTEGER,
|
|
||||||
msg,
|
msg,
|
||||||
size);
|
size,
|
||||||
|
TY_INTEGER,
|
||||||
|
TY_FLOAT,
|
||||||
|
TYPE_END);
|
||||||
if (!status)
|
if (!status)
|
||||||
{
|
{
|
||||||
return status;
|
return status;
|
||||||
|
@ -167,24 +177,56 @@ int cstatic_check(cstatic* self, node* ast, char* msg, size_t size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check_type(cstatic* self, node* lhs, int rhs,
|
int cstatic_check_type(cstatic* self, node* lhs,
|
||||||
char* msg, size_t size)
|
char* msg, size_t size, int types, ...)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(lhs);
|
assert(lhs);
|
||||||
|
char aze[512];
|
||||||
|
node_str(lhs, aze, 512);
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, types);
|
||||||
|
int rhs = types;
|
||||||
|
|
||||||
int left = cstatic_resolve(self, lhs);
|
int left = cstatic_resolve(self, lhs);
|
||||||
|
|
||||||
if (left != rhs)
|
int all_types[TY_TYPE_COUNT];
|
||||||
|
memset(all_types, TYPE_END, TY_TYPE_COUNT * sizeof(int));
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
while (rhs != TYPE_END)
|
||||||
{
|
{
|
||||||
snprintf(msg, size, "E(%d): expected '%s', got '%s'.",
|
all_types[i] = rhs;
|
||||||
lhs->lineno,
|
|
||||||
TypesStr[left],
|
if (left == rhs)
|
||||||
TypesStr[rhs]);
|
{
|
||||||
return 0;
|
va_end(args);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
rhs = va_arg(args, int);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
size_t sz = snprintf(msg, size, "E(%d): type mismatch, got '%s', ",
|
||||||
|
lhs->lineno,
|
||||||
|
TypesStr[left]);
|
||||||
|
|
||||||
|
sz += snprintf(msg + sz, size - sz, "expected: \n");
|
||||||
|
|
||||||
|
size_t j = 0;
|
||||||
|
|
||||||
|
while (all_types[j] != TYPE_END)
|
||||||
|
{
|
||||||
|
sz += snprintf(msg + sz, size - sz, "\t '%s'\n",
|
||||||
|
TypesStr[all_types[j]]);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
||||||
|
#define TYPE_END (-1)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int _unused;
|
int _unused;
|
||||||
} cstatic;
|
} cstatic;
|
||||||
|
@ -14,8 +16,8 @@ void cstatic_free(cstatic* self);
|
||||||
int cstatic_resolve(cstatic* self, node* ast);
|
int cstatic_resolve(cstatic* self, node* ast);
|
||||||
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size);
|
int cstatic_check(cstatic* self, node* ast, char* msg, size_t size);
|
||||||
|
|
||||||
int cstatic_check_type(cstatic* self, node* lhs, int rhs,
|
int cstatic_check_type(cstatic* self, node* lhs,
|
||||||
char* msg, size_t size);
|
char* msg, size_t size, int types, ...);
|
||||||
|
|
||||||
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
int cstatic_check_same_type(cstatic* self, node* lhs, node* rhs,
|
||||||
char* msg, size_t size);
|
char* msg, size_t size);
|
||||||
|
|
|
@ -11,6 +11,7 @@ COMMENT ::[^\n]*
|
||||||
WHITESPACES [ \t]+
|
WHITESPACES [ \t]+
|
||||||
BOOLEAN true|false
|
BOOLEAN true|false
|
||||||
INTEGER -?[0-9]+
|
INTEGER -?[0-9]+
|
||||||
|
FLOAT -?[0-9]+\.[0-9]+
|
||||||
|
|
||||||
%%
|
%%
|
||||||
"\n" { line++; }
|
"\n" { line++; }
|
||||||
|
@ -38,6 +39,11 @@ INTEGER -?[0-9]+
|
||||||
return BOOLEAN;
|
return BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{FLOAT} {
|
||||||
|
yylval.str = yytext;
|
||||||
|
return FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
{INTEGER} {
|
{INTEGER} {
|
||||||
yylval.str = yytext;
|
yylval.str = yytext;
|
||||||
return INTEGER;
|
return INTEGER;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#define NODE_TYPE(G) \
|
#define NODE_TYPE(G) \
|
||||||
G(NODE_PROG), \
|
G(NODE_PROG), \
|
||||||
G(NODE_BOOLEAN), G(NODE_INTEGER), \
|
G(NODE_BOOLEAN), G(NODE_INTEGER), G(NODE_FLOAT), \
|
||||||
G(NODE_AND), G(NODE_OR), G(NODE_NOT), \
|
G(NODE_AND), G(NODE_OR), G(NODE_NOT), \
|
||||||
G(NODE_EQ), G(NODE_NE), \
|
G(NODE_EQ), G(NODE_NE), \
|
||||||
G(NODE_ASSERT), \
|
G(NODE_ASSERT), \
|
||||||
|
|
|
@ -17,7 +17,15 @@
|
||||||
G(OP_IMOD), \
|
G(OP_IMOD), \
|
||||||
G(OP_IPOW), \
|
G(OP_IPOW), \
|
||||||
G(OP_IUADD), \
|
G(OP_IUADD), \
|
||||||
G(OP_IUSUB),
|
G(OP_IUSUB), \
|
||||||
|
G(OP_FADD), \
|
||||||
|
G(OP_FSUB), \
|
||||||
|
G(OP_FMUL), \
|
||||||
|
G(OP_FDIV), \
|
||||||
|
G(OP_FMOD), \
|
||||||
|
G(OP_FPOW), \
|
||||||
|
G(OP_FUADD), \
|
||||||
|
G(OP_FUSUB),
|
||||||
|
|
||||||
enum Opcodes {
|
enum Opcodes {
|
||||||
OPCODES(GEN_ENUM)
|
OPCODES(GEN_ENUM)
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
%left ASSERT
|
%left ASSERT
|
||||||
%token <str> BOOLEAN
|
%token <str> BOOLEAN INTEGER FLOAT
|
||||||
%token <str> INTEGER
|
|
||||||
%left EQ NE
|
%left EQ NE
|
||||||
%left AND
|
%left AND
|
||||||
%left OR
|
%left OR
|
||||||
|
@ -179,6 +178,12 @@ expr:
|
||||||
node_init(n, NODE_INTEGER, $1, line);
|
node_init(n, NODE_INTEGER, $1, line);
|
||||||
$$ = n;
|
$$ = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| FLOAT {
|
||||||
|
node* n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_FLOAT, $1, line);
|
||||||
|
$$ = n;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#define TYPES(G) \
|
#define TYPES(G) \
|
||||||
G(TY_NIL), \
|
G(TY_NIL), \
|
||||||
G(TY_BOOLEAN), \
|
G(TY_BOOLEAN), \
|
||||||
G(TY_INTEGER),
|
G(TY_INTEGER), \
|
||||||
|
G(TY_FLOAT), \
|
||||||
|
G(TY_TYPE_COUNT)
|
||||||
|
|
||||||
enum Types {
|
enum Types {
|
||||||
TYPES(GEN_ENUM)
|
TYPES(GEN_ENUM)
|
||||||
|
|
15
src/value.c
15
src/value.c
|
@ -20,6 +20,16 @@ void value_init_integer(value* self, int integer, int lineno)
|
||||||
type_init(self->type, TY_INTEGER);
|
type_init(self->type, TY_INTEGER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void value_init_float(value* self, float real_float, int lineno)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->val.real_float = real_float;
|
||||||
|
self->lineno = lineno;
|
||||||
|
|
||||||
|
self->type = malloc(sizeof(type));
|
||||||
|
type_init(self->type, TY_FLOAT);
|
||||||
|
}
|
||||||
|
|
||||||
void value_free(value* self)
|
void value_free(value* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -60,6 +70,11 @@ int value_equals(value* self, value* rhs)
|
||||||
return self->val.integer == rhs->val.integer;
|
return self->val.integer == rhs->val.integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self->type->base_type == TY_FLOAT)
|
||||||
|
{
|
||||||
|
return self->val.real_float == rhs->val.real_float;
|
||||||
|
}
|
||||||
|
|
||||||
size_t const SZ = 512;
|
size_t const SZ = 512;
|
||||||
char ty_str[SZ];
|
char ty_str[SZ];
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,13 @@ typedef struct {
|
||||||
union {
|
union {
|
||||||
int boolean;
|
int boolean;
|
||||||
int integer;
|
int integer;
|
||||||
|
float real_float;
|
||||||
} val;
|
} val;
|
||||||
} value;
|
} value;
|
||||||
|
|
||||||
void value_init_boolean(value* self, int boolean, int lineno);
|
void value_init_boolean(value* self, int boolean, int lineno);
|
||||||
void value_init_integer(value* self, int integer, int lineno);
|
void value_init_integer(value* self, int integer, int lineno);
|
||||||
|
void value_init_float(value* self, float real_float, int lineno);
|
||||||
void value_free(value* self);
|
void value_free(value* self);
|
||||||
|
|
||||||
value* value_new_clone(value* self);
|
value* value_new_clone(value* self);
|
||||||
|
|
146
src/vm.c
146
src/vm.c
|
@ -54,6 +54,16 @@ void vm_exec(vm* self, program* prog)
|
||||||
case OP_IDIV: vm_idiv(self); break;
|
case OP_IDIV: vm_idiv(self); break;
|
||||||
case OP_IMOD: vm_imod(self); break;
|
case OP_IMOD: vm_imod(self); break;
|
||||||
case OP_IPOW: vm_ipow(self); break;
|
case OP_IPOW: vm_ipow(self); break;
|
||||||
|
|
||||||
|
case OP_FADD: vm_fadd(self); break;
|
||||||
|
case OP_FUADD: vm_fuadd(self); break;
|
||||||
|
case OP_FSUB: vm_fsub(self); break;
|
||||||
|
case OP_FUSUB: vm_fusub(self); break;
|
||||||
|
case OP_FMUL: vm_fmul(self); break;
|
||||||
|
case OP_FDIV: vm_fdiv(self); break;
|
||||||
|
case OP_FMOD: vm_fmod(self); break;
|
||||||
|
case OP_FPOW: vm_fpow(self); break;
|
||||||
|
|
||||||
case OP_ASSERT: vm_assert(self); break;
|
case OP_ASSERT: vm_assert(self); break;
|
||||||
default: {
|
default: {
|
||||||
fprintf(stderr, "unknown opcode %s\n",
|
fprintf(stderr, "unknown opcode %s\n",
|
||||||
|
@ -303,6 +313,142 @@ void vm_ipow(vm* self)
|
||||||
self->pc++;
|
self->pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vm_fadd(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(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_fuadd(vm* self)
|
||||||
|
{
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(val, lhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_fsub(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(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_fusub(vm* self)
|
||||||
|
{
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(val, -lhs->val.real_float, lhs->lineno);
|
||||||
|
vm_push_value(self, val);
|
||||||
|
|
||||||
|
value_free(lhs);
|
||||||
|
free(lhs);
|
||||||
|
|
||||||
|
self->pc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vm_fmul(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(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_fdiv(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(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_fmod(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(val, fmod(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_fpow(vm* self)
|
||||||
|
{
|
||||||
|
value* rhs = vm_pop_value(self);
|
||||||
|
value* lhs = vm_pop_value(self);
|
||||||
|
|
||||||
|
value* val = malloc(sizeof(value));
|
||||||
|
value_init_float(val, pow(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_eq(vm* self)
|
void vm_eq(vm* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
8
src/vm.h
8
src/vm.h
|
@ -38,6 +38,14 @@ void vm_idiv(vm* self);
|
||||||
void vm_imod(vm* self);
|
void vm_imod(vm* self);
|
||||||
void vm_ipow(vm* self);
|
void vm_ipow(vm* self);
|
||||||
|
|
||||||
|
void vm_fadd(vm* self);
|
||||||
|
void vm_fuadd(vm* self);
|
||||||
|
void vm_fsub(vm* self);
|
||||||
|
void vm_fusub(vm* self);
|
||||||
|
void vm_fmul(vm* self);
|
||||||
|
void vm_fdiv(vm* self);
|
||||||
|
void vm_fmod(vm* self);
|
||||||
|
void vm_fpow(vm* self);
|
||||||
|
|
||||||
void vm_eq(vm* self);
|
void vm_eq(vm* self);
|
||||||
void vm_assert(vm* self);
|
void vm_assert(vm* self);
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
5 + 2.0
|
||||||
|
3.0 + 9
|
||||||
|
5 - 2.0
|
||||||
|
3.0 - 9
|
||||||
|
5 * 2.0
|
||||||
|
3.0 * 9
|
||||||
|
5 / 2.0
|
||||||
|
3.0 / 9
|
||||||
|
5 % 2.0
|
||||||
|
3.0 % 9
|
||||||
|
1.2 ^ 3
|
||||||
|
|
||||||
|
true + 2.0
|
||||||
|
3.0 + false
|
||||||
|
false - 2.0
|
||||||
|
3.0 - true
|
||||||
|
false * 2.0
|
||||||
|
false * 9
|
||||||
|
5 / true
|
||||||
|
true / 9
|
||||||
|
5 % false
|
||||||
|
true % 9
|
||||||
|
(false && false) ^ 3
|
||||||
|
|
||||||
|
1.2 && 2.3
|
||||||
|
1.2 || 2.3
|
||||||
|
!12.0
|
|
@ -0,0 +1,13 @@
|
||||||
|
assert 5.2 == 5.2
|
||||||
|
assert 5.2 != 5.3
|
||||||
|
|
||||||
|
:: Arithmetic
|
||||||
|
assert 7.2 == 5.1 + 2.1
|
||||||
|
assert 2.0 == + 2.0
|
||||||
|
assert 3.0 == 5.0 - 2.0
|
||||||
|
assert -5.0 == - 5.0
|
||||||
|
assert 10.0 == 5.0 * 2.0
|
||||||
|
assert 2.5 == 5.0 / 2.0
|
||||||
|
assert 1.0 == 5.0 % 2.0
|
||||||
|
assert 0.5 == 5.0 % 1.5
|
||||||
|
assert 25.0 == 5.0 ^ 2.0
|
Loading…
Reference in New Issue