alang eval test
This commit is contained in:
@@ -285,6 +285,8 @@ if (flags.with_eval) {
|
|||||||
project.add_define("WITH_EVAL");
|
project.add_define("WITH_EVAL");
|
||||||
project.add_cfiles("sources/libs/quickjs-amalgam.c");
|
project.add_cfiles("sources/libs/quickjs-amalgam.c");
|
||||||
project.add_define("QJS_BUILD_LIBC");
|
project.add_define("QJS_BUILD_LIBC");
|
||||||
|
// project.add_cfiles("tools/amake/alang.c");
|
||||||
|
// project.add_cfiles("tools/amake/alang_eval.c");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.with_iron) {
|
if (flags.with_iron) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
|||||||
|
// Based on https://github.com/Kode/Kongruent by RobDangerous
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define OPCODES_SIZE (1024 * 1024)
|
||||||
|
|
||||||
|
typedef uint32_t type_id;
|
||||||
|
typedef size_t name_id;
|
||||||
|
|
||||||
|
typedef struct attribute {
|
||||||
|
name_id name;
|
||||||
|
double parameters[16];
|
||||||
|
uint8_t paramters_count;
|
||||||
|
} attribute;
|
||||||
|
|
||||||
|
typedef struct attributes {
|
||||||
|
attribute attributes[64];
|
||||||
|
uint8_t attributes_count;
|
||||||
|
} attribute_list;
|
||||||
|
|
||||||
|
typedef struct unresolved_type_ref {
|
||||||
|
name_id name;
|
||||||
|
uint32_t array_size;
|
||||||
|
} unresolved_type_ref;
|
||||||
|
|
||||||
|
typedef struct type_ref {
|
||||||
|
type_id type;
|
||||||
|
unresolved_type_ref unresolved;
|
||||||
|
} type_ref;
|
||||||
|
|
||||||
|
typedef struct opcodes {
|
||||||
|
uint8_t o[OPCODES_SIZE];
|
||||||
|
size_t size;
|
||||||
|
} opcodes;
|
||||||
|
|
||||||
|
typedef struct function {
|
||||||
|
attribute_list attributes;
|
||||||
|
name_id name;
|
||||||
|
type_ref return_type;
|
||||||
|
name_id parameter_names[256];
|
||||||
|
type_ref parameter_types[256];
|
||||||
|
name_id parameter_attributes[256];
|
||||||
|
uint8_t parameters_size;
|
||||||
|
struct statement *block;
|
||||||
|
opcodes code;
|
||||||
|
} function;
|
||||||
|
|
||||||
|
typedef uint32_t function_id;
|
||||||
|
|
||||||
|
// extern type_id void_id;
|
||||||
|
// extern type_id float_id;
|
||||||
|
// extern type_id int_id;
|
||||||
|
// extern type_id uint_id;
|
||||||
|
// extern type_id bool_id;
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
#include "alang.h"
|
||||||
|
|
||||||
|
static void _indent(FILE *out, int indent) {
|
||||||
|
for (int i = 0; i < indent; ++i) {
|
||||||
|
fprintf(out, " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *to_c_type(type_id type) {
|
||||||
|
if (type == float_id) return "f32";
|
||||||
|
if (type == int_id) return "i32";
|
||||||
|
if (type == uint_id) return "u32";
|
||||||
|
if (type == bool_id) return "bool";
|
||||||
|
return "void";
|
||||||
|
}
|
||||||
|
|
||||||
|
void alang_c(const char *output) {
|
||||||
|
FILE *out = fopen(output, "w");
|
||||||
|
fprintf(out, "#include <stdbool.h>\n");
|
||||||
|
fprintf(out, "#include <stdio.h>\n");
|
||||||
|
fprintf(out, "#include <math.h>\n\n");
|
||||||
|
|
||||||
|
function *main_func = NULL;
|
||||||
|
for (function_id i = 0; get_function(i) != NULL; ++i) {
|
||||||
|
function *f = get_function(i);
|
||||||
|
if (strcmp(get_name(f->name), "main") == 0) {
|
||||||
|
main_func = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < allocated_globals_size; ++i) {
|
||||||
|
global *g = allocated_globals[i].g;
|
||||||
|
fprintf(out, "%s var_%llu = ", to_c_type(g->type), allocated_globals[i].variable_id);
|
||||||
|
if (g->value.kind == GLOBAL_VALUE_FLOAT) {
|
||||||
|
fprintf(out, "%ff;\n", g->value.value.floats[0]);
|
||||||
|
}
|
||||||
|
else if (g->value.kind == GLOBAL_VALUE_INT) {
|
||||||
|
fprintf(out, "%d;\n", g->value.value.ints[0]);
|
||||||
|
}
|
||||||
|
else if (g->value.kind == GLOBAL_VALUE_BOOL) {
|
||||||
|
fprintf(out, "%s;\n", g->value.value.b ? "true" : "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allocated_globals_size > 0) {
|
||||||
|
fprintf(out, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(out, "int main() {\n");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < main_func->block->block.vars.size; ++i) {
|
||||||
|
local_variable *var = &main_func->block->block.vars.v[i];
|
||||||
|
_indent(out, 1);
|
||||||
|
fprintf(out, "%s var_%llu;\n", to_c_type(var->type.type), var->variable_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
int indent = 1;
|
||||||
|
while (pos < main_func->code.size) {
|
||||||
|
opcode *op = (opcode *)&main_func->code.o[pos];
|
||||||
|
pos += op->size;
|
||||||
|
|
||||||
|
_indent(out, indent);
|
||||||
|
switch (op->type) {
|
||||||
|
case OPCODE_VAR: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_FLOAT_CONSTANT: {
|
||||||
|
fprintf(out, "%s var_%llu = %ff;\n",
|
||||||
|
to_c_type(op->op_load_float_constant.to.type.type),
|
||||||
|
op->op_load_float_constant.to.index,
|
||||||
|
op->op_load_float_constant.number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_INT_CONSTANT: {
|
||||||
|
fprintf(out, "%s var_%llu = %d;\n",
|
||||||
|
to_c_type(op->op_load_int_constant.to.type.type),
|
||||||
|
op->op_load_int_constant.to.index,
|
||||||
|
op->op_load_int_constant.number);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_BOOL_CONSTANT: {
|
||||||
|
fprintf(out, "%s var_%llu = %s;\n",
|
||||||
|
to_c_type(op->op_load_bool_constant.to.type.type),
|
||||||
|
op->op_load_bool_constant.to.index,
|
||||||
|
op->op_load_bool_constant.boolean ? "true" : "false");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_STORE_VARIABLE: {
|
||||||
|
fprintf(out, "var_%llu = ", op->op_store_var.to.index);
|
||||||
|
fprintf(out, "var_%llu;\n", op->op_store_var.from.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_ADD:
|
||||||
|
case OPCODE_SUB:
|
||||||
|
case OPCODE_MULTIPLY:
|
||||||
|
case OPCODE_DIVIDE:
|
||||||
|
case OPCODE_MOD:
|
||||||
|
case OPCODE_EQUALS:
|
||||||
|
case OPCODE_NOT_EQUALS:
|
||||||
|
case OPCODE_GREATER:
|
||||||
|
case OPCODE_GREATER_EQUAL:
|
||||||
|
case OPCODE_LESS:
|
||||||
|
case OPCODE_LESS_EQUAL:
|
||||||
|
case OPCODE_AND:
|
||||||
|
case OPCODE_OR:
|
||||||
|
case OPCODE_BITWISE_XOR:
|
||||||
|
case OPCODE_BITWISE_AND:
|
||||||
|
case OPCODE_BITWISE_OR:
|
||||||
|
case OPCODE_LEFT_SHIFT:
|
||||||
|
case OPCODE_RIGHT_SHIFT: {
|
||||||
|
const char *op_str = "";
|
||||||
|
switch (op->type) {
|
||||||
|
case OPCODE_ADD: op_str = "+"; break;
|
||||||
|
case OPCODE_SUB: op_str = "-"; break;
|
||||||
|
case OPCODE_MULTIPLY: op_str = "*"; break;
|
||||||
|
case OPCODE_DIVIDE: op_str = "/"; break;
|
||||||
|
case OPCODE_MOD: op_str = "%"; break;
|
||||||
|
case OPCODE_EQUALS: op_str = "=="; break;
|
||||||
|
case OPCODE_NOT_EQUALS: op_str = "!="; break;
|
||||||
|
case OPCODE_GREATER: op_str = ">"; break;
|
||||||
|
case OPCODE_GREATER_EQUAL: op_str = ">="; break;
|
||||||
|
case OPCODE_LESS: op_str = "<"; break;
|
||||||
|
case OPCODE_LESS_EQUAL: op_str = "<="; break;
|
||||||
|
case OPCODE_AND: op_str = "&&"; break;
|
||||||
|
case OPCODE_OR: op_str = "||"; break;
|
||||||
|
case OPCODE_BITWISE_XOR: op_str = "^"; break;
|
||||||
|
case OPCODE_BITWISE_AND: op_str = "&"; break;
|
||||||
|
case OPCODE_BITWISE_OR: op_str = "|"; break;
|
||||||
|
case OPCODE_LEFT_SHIFT: op_str = "<<"; break;
|
||||||
|
case OPCODE_RIGHT_SHIFT: op_str = ">>"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
fprintf(out, "%s var_%llu = ",
|
||||||
|
to_c_type(op->op_binary.result.type.type),
|
||||||
|
op->op_binary.result.index);
|
||||||
|
fprintf(out, "var_%llu", op->op_binary.left.index);
|
||||||
|
fprintf(out, " %s ", op_str);
|
||||||
|
fprintf(out, "var_%llu;\n", op->op_binary.right.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_NOT: {
|
||||||
|
fprintf(out, "%s var_%llu = !",
|
||||||
|
to_c_type(op->op_not.to.type.type),
|
||||||
|
op->op_not.to.index);
|
||||||
|
fprintf(out, "var_%llu;\n", op->op_not.from.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_NEGATE: {
|
||||||
|
fprintf(out, "%s var_%llu = -",
|
||||||
|
to_c_type(op->op_negate.to.type.type),
|
||||||
|
op->op_negate.to.index);
|
||||||
|
fprintf(out, "var_%llu;\n", op->op_negate.from.index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_IF: {
|
||||||
|
fprintf(out, "if (");
|
||||||
|
fprintf(out, "var_%llu) {\n", op->op_if.condition.index);
|
||||||
|
indent++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_START: {
|
||||||
|
fprintf(out, "while_%llu:;\n", op->op_while_start.start_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_CONDITION: {
|
||||||
|
fprintf(out, "if (!");
|
||||||
|
fprintf(out, "var_%llu) goto while_%llu;\n",
|
||||||
|
op->op_while.condition.index, op->op_while.end_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_END: {
|
||||||
|
fprintf(out, "goto while_%llu;\n", op->op_while_end.start_id);
|
||||||
|
_indent(out, indent);
|
||||||
|
fprintf(out, "while_%llu:;\n", op->op_while_end.end_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BLOCK_START: {
|
||||||
|
fprintf(out, "{\n");
|
||||||
|
indent++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BLOCK_END: {
|
||||||
|
indent--;
|
||||||
|
_indent(out, indent);
|
||||||
|
fprintf(out, "}\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_RETURN: {
|
||||||
|
if (op->op_return.var.index != 0) {
|
||||||
|
fprintf(out, "return ");
|
||||||
|
fprintf(out, "var_%llu;\n", op->op_return.var.index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(out, "return 0;\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_CALL: {
|
||||||
|
if (strcmp(get_name(op->op_call.func), "print") == 0) {
|
||||||
|
fprintf(out, "%s var_%llu = %s(",
|
||||||
|
to_c_type(op->op_call.var.type.type),
|
||||||
|
op->op_call.var.index,
|
||||||
|
get_name(op->op_call.func));
|
||||||
|
fprintf(out, "var_%llu);\n", op->op_call.parameters[0].index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(out, " return 0;\n");
|
||||||
|
fprintf(out, "}\n");
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
@@ -0,0 +1,411 @@
|
|||||||
|
#include "alang.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef union value {
|
||||||
|
float f;
|
||||||
|
int i;
|
||||||
|
bool b;
|
||||||
|
} value;
|
||||||
|
|
||||||
|
typedef struct variable_storage {
|
||||||
|
value val;
|
||||||
|
type_id type;
|
||||||
|
} variable_storage;
|
||||||
|
|
||||||
|
typedef struct interpreter_state {
|
||||||
|
variable_storage vars[1024];
|
||||||
|
size_t pos;
|
||||||
|
} interpreter_state;
|
||||||
|
|
||||||
|
static value get_variable_value(interpreter_state *state, variable var) {
|
||||||
|
return state->vars[var.index].val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_variable_value(interpreter_state *state, variable var, value v) {
|
||||||
|
state->vars[var.index].val = v;
|
||||||
|
state->vars[var.index].type = var.type.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void eval() {
|
||||||
|
interpreter_state state = {0};
|
||||||
|
function *main_func = NULL;
|
||||||
|
|
||||||
|
for (function_id i = 0; get_function(i) != NULL; ++i) {
|
||||||
|
function *f = get_function(i);
|
||||||
|
if (strcmp(get_name(f->name), "main") == 0) {
|
||||||
|
main_func = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < allocated_globals_size; ++i) {
|
||||||
|
global *g = allocated_globals[i].g;
|
||||||
|
uint64_t var_index = allocated_globals[i].variable_id;
|
||||||
|
if (g->value.kind == GLOBAL_VALUE_FLOAT) {
|
||||||
|
state.vars[var_index].val.f = g->value.value.floats[0];
|
||||||
|
state.vars[var_index].type = g->type;
|
||||||
|
}
|
||||||
|
else if (g->value.kind == GLOBAL_VALUE_INT) {
|
||||||
|
state.vars[var_index].val.i = g->value.value.ints[0];
|
||||||
|
state.vars[var_index].type = g->type;
|
||||||
|
}
|
||||||
|
else if (g->value.kind == GLOBAL_VALUE_BOOL) {
|
||||||
|
state.vars[var_index].val.b = g->value.value.b;
|
||||||
|
state.vars[var_index].type = g->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.pos = 0;
|
||||||
|
opcodes *code = &main_func->code;
|
||||||
|
|
||||||
|
while (state.pos < code->size) {
|
||||||
|
opcode *op = (opcode *)&code->o[state.pos];
|
||||||
|
state.pos += op->size;
|
||||||
|
|
||||||
|
switch (op->type) {
|
||||||
|
case OPCODE_VAR: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_FLOAT_CONSTANT: {
|
||||||
|
value v;
|
||||||
|
v.f = op->op_load_float_constant.number;
|
||||||
|
set_variable_value(&state, op->op_load_float_constant.to, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_INT_CONSTANT: {
|
||||||
|
value v;
|
||||||
|
v.i = op->op_load_int_constant.number;
|
||||||
|
set_variable_value(&state, op->op_load_int_constant.to, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LOAD_BOOL_CONSTANT: {
|
||||||
|
value v;
|
||||||
|
v.b = op->op_load_bool_constant.boolean;
|
||||||
|
set_variable_value(&state, op->op_load_bool_constant.to, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_STORE_VARIABLE: {
|
||||||
|
value v = get_variable_value(&state, op->op_store_var.from);
|
||||||
|
set_variable_value(&state, op->op_store_var.to, v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_ADD: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id result_type = op->op_binary.result.type.type;
|
||||||
|
if (result_type == float_id) {
|
||||||
|
float l = (op->op_binary.left.type.type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (op->op_binary.right.type.type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.f = l + r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.i = left.i + right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_SUB: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id result_type = op->op_binary.result.type.type;
|
||||||
|
if (result_type == float_id) {
|
||||||
|
float l = (op->op_binary.left.type.type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (op->op_binary.right.type.type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.f = l - r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.i = left.i - right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_MULTIPLY: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id result_type = op->op_binary.result.type.type;
|
||||||
|
if (result_type == float_id) {
|
||||||
|
float l = (op->op_binary.left.type.type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (op->op_binary.right.type.type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.f = l * r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.i = left.i * right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_DIVIDE: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id result_type = op->op_binary.result.type.type;
|
||||||
|
if (result_type == float_id) {
|
||||||
|
float l = (op->op_binary.left.type.type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (op->op_binary.right.type.type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.f = l / r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.i = left.i / right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_MOD: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i % right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_EQUALS: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l == r;
|
||||||
|
}
|
||||||
|
else if (left_type == bool_id && right_type == bool_id) {
|
||||||
|
result.b = left.b == right.b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i == right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_NOT_EQUALS: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l != r;
|
||||||
|
}
|
||||||
|
else if (left_type == bool_id && right_type == bool_id) {
|
||||||
|
result.b = left.b != right.b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i != right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_GREATER: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l > r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i > right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_GREATER_EQUAL: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l >= r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i >= right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LESS: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l < r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i < right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LESS_EQUAL: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
type_id left_type = op->op_binary.left.type.type;
|
||||||
|
type_id right_type = op->op_binary.right.type.type;
|
||||||
|
if (left_type == float_id || right_type == float_id) {
|
||||||
|
float l = (left_type == float_id) ? left.f : (float)left.i;
|
||||||
|
float r = (right_type == float_id) ? right.f : (float)right.i;
|
||||||
|
result.b = l <= r;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.b = left.i <= right.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_AND: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.b = left.b && right.b;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_OR: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.b = left.b || right.b;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BITWISE_XOR: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i ^ right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BITWISE_AND: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i & right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BITWISE_OR: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i | right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_LEFT_SHIFT: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i << right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_RIGHT_SHIFT: {
|
||||||
|
value left = get_variable_value(&state, op->op_binary.left);
|
||||||
|
value right = get_variable_value(&state, op->op_binary.right);
|
||||||
|
value result;
|
||||||
|
result.i = left.i >> right.i;
|
||||||
|
set_variable_value(&state, op->op_binary.result, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_NOT: {
|
||||||
|
value from = get_variable_value(&state, op->op_not.from);
|
||||||
|
value result;
|
||||||
|
result.b = !from.b;
|
||||||
|
set_variable_value(&state, op->op_not.to, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_NEGATE: {
|
||||||
|
value from = get_variable_value(&state, op->op_negate.from);
|
||||||
|
value result;
|
||||||
|
if (op->op_negate.from.type.type == float_id) {
|
||||||
|
result.f = -from.f;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.i = -from.i;
|
||||||
|
}
|
||||||
|
set_variable_value(&state, op->op_negate.to, result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_IF: {
|
||||||
|
value condition = get_variable_value(&state, op->op_if.condition);
|
||||||
|
if (!condition.b) {
|
||||||
|
state.pos = op->op_if.end_id;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_START: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_CONDITION: {
|
||||||
|
value condition = get_variable_value(&state, op->op_while.condition);
|
||||||
|
if (!condition.b) {
|
||||||
|
state.pos = op->op_while.end_id;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_WHILE_END: {
|
||||||
|
state.pos = op->op_while_end.start_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_BLOCK_START:
|
||||||
|
case OPCODE_BLOCK_END: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OPCODE_RETURN: {
|
||||||
|
if (op->op_return.var.index != 0) {
|
||||||
|
value return_val = get_variable_value(&state, op->op_return.var);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case OPCODE_CALL: {
|
||||||
|
if (strcmp(get_name(op->op_call.func), "print") == 0) {
|
||||||
|
value param = get_variable_value(&state, op->op_call.parameters[0]);
|
||||||
|
value result;
|
||||||
|
printf("%f\n", param.f);
|
||||||
|
set_variable_value(&state, op->op_call.var, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void alang_eval(char *data) {
|
||||||
|
names_init();
|
||||||
|
types_init();
|
||||||
|
functions_init();
|
||||||
|
globals_init();
|
||||||
|
|
||||||
|
char *filename = "main.kong";
|
||||||
|
tokens tokens = tokenize(filename, data);
|
||||||
|
parse(filename, &tokens);
|
||||||
|
resolve_types();
|
||||||
|
// allocate_globals();
|
||||||
|
for (function_id i = 0; get_function(i) != NULL; ++i) {
|
||||||
|
compile_function_block(&get_function(i)->code, get_function(i)->block);
|
||||||
|
}
|
||||||
|
eval();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user