native function support.

main
bog 2024-02-17 21:49:39 +01:00
parent 09bbc31320
commit 76e0cdbeef
21 changed files with 627 additions and 35 deletions

View File

@ -6,6 +6,7 @@
#include <compiler.h>
#include <vm.h>
#include <sym_table.h>
#include <native.h>
char* load_new_source(char const* path)
{
@ -159,8 +160,16 @@ int main(int argc, char** argv)
printf("%s\n", msg);
}
struct vec natives;
vec_init(&natives, 1);
struct sym_table globals;
sym_table_init(&globals, NULL);
populate_native(&natives, &globals);
struct type_checker checker;
type_checker_init(&checker);
type_checker_init(&checker, &globals);
if (type_checker_check(&checker, ast) != 0)
{
@ -171,6 +180,12 @@ int main(int argc, char** argv)
type_checker_free(&checker);
sym_table_free(&globals);
for (size_t i=0; i<natives.size; i++)
{ value_free(natives.data[i]); }
vec_free_elements(&natives);
vec_free(&natives);
if (ast)
{
node_free(ast);
@ -196,7 +211,7 @@ int main(int argc, char** argv)
program_init(&program);
struct compiler compiler;
compiler_init(&compiler);
compiler_init(&compiler, &globals);
if (compiler_compile(&compiler, ast, &program) != 0)
{
@ -209,6 +224,12 @@ int main(int argc, char** argv)
program_free(&program);
type_checker_free(&checker);
sym_table_free(&globals);
for (size_t i=0; i<natives.size; i++)
{ value_free(natives.data[i]); }
vec_free_elements(&natives);
vec_free(&natives);
if (ast)
{
@ -246,7 +267,7 @@ int main(int argc, char** argv)
}
struct vm vm;
vm_init(&vm);
vm_init(&vm, &natives);
err = vm_exec(&vm, &program);
@ -262,6 +283,12 @@ int main(int argc, char** argv)
compiler_free(&compiler);
program_free(&program);
type_checker_free(&checker);
sym_table_free(&globals);
for (size_t i=0; i<natives.size; i++)
{ value_free(natives.data[i]); }
vec_free_elements(&natives);
vec_free(&natives);
if (ast)
{
@ -297,6 +324,12 @@ int main(int argc, char** argv)
compiler_free(&compiler);
program_free(&program);
type_checker_free(&checker);
sym_table_free(&globals);
for (size_t i=0; i<natives.size; i++)
{ value_free(natives.data[i]); }
vec_free_elements(&natives);
vec_free(&natives);
if (ast)
{

View File

@ -11,6 +11,7 @@ add_library(gux-lang OBJECT
src/type.c
src/value.c
src/fun.c
src/native.c
src/type_resolver.c
src/type_checker.c
src/sym_table.c

View File

@ -6,14 +6,15 @@
#include "sym_table.h"
#include "type.h"
#include "type_checker.h"
#include "type_resolver.h"
#include "value.h"
#include "vec.h"
#include "fun.h"
void compiler_init(struct compiler* self)
void compiler_init(struct compiler* self, struct sym_table* global)
{
assert(self);
sym_table_init(&self->sym_table);
sym_table_init(&self->sym_table, global);
memset(self->error_msg, 0, GUX_STR_SIZE);
self->stack_size = 0;
vec_init(&self->loops, 1);
@ -55,7 +56,7 @@ int compiler_compile(struct compiler* self,
sym_table_push_table(&self->sym_table);
struct compiler compiler;
compiler_init(&compiler);
compiler_init(&compiler, self->sym_table.prev);
struct vec idents;
vec_init(&idents, 1);
@ -75,7 +76,7 @@ int compiler_compile(struct compiler* self,
struct node* ident = idents.data[j];
struct type* ty = malloc(sizeof(struct type));
type_init_from_node(ty, param);
compiler_get_type(self, param, ty);
sym_table_declare_const(&compiler.sym_table,
ident->value,
@ -129,7 +130,15 @@ int compiler_compile(struct compiler* self,
assert(entry);
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
if (entry->is_global)
{
compiler_gen_instr(self, program, OP_GLOAD, entry->addr);
}
else
{
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
}
compiler_gen_instr(self, program, OP_CALL, args->children.size);
} break;
@ -261,7 +270,14 @@ int compiler_compile(struct compiler* self,
return 1;
}
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
if (entry->is_global)
{
compiler_gen_instr(self, program, OP_GLOAD, entry->addr);
}
else
{
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
}
} break;
case NODE_CONSTDECL:
@ -278,7 +294,8 @@ int compiler_compile(struct compiler* self,
}
struct type* ty = malloc(sizeof(struct type));
type_init_from_node(ty, node->children.data[0]);
type_init(ty, TYPE_VOID);
compiler_get_type(self, node->children.data[0], ty);
sym_table_declare(&self->sym_table, node->value, ty,
node->type == NODE_VARDECL);
@ -315,6 +332,7 @@ int compiler_compile(struct compiler* self,
case NODE_STRING: {
struct value* val = malloc(sizeof(struct value));
value_init_string(val, node->value, node->line);
size_t addr = program_push_constant(program, val);
compiler_gen_instr(self, program, OP_PUSH, addr);
@ -598,6 +616,7 @@ size_t compiler_gen_instr(struct compiler* self,
case OP_CALL: break;
case OP_LOAD:
case OP_GLOAD:
case OP_PUSH: self->stack_size += 1; break;
case OP_LT:
@ -627,3 +646,14 @@ size_t compiler_gen_instr(struct compiler* self,
return addr;
}
size_t compiler_get_type(struct compiler* self,
struct node* node,
struct type* type)
{
struct type_resolver resolver;
type_resolver_init(&resolver, &self->sym_table);
size_t err = type_resolver_resolve(&resolver, node, type);
type_resolver_free(&resolver);
return err;
}

View File

@ -19,7 +19,7 @@ struct compiler {
struct vec loops;
};
void compiler_init(struct compiler* self);
void compiler_init(struct compiler* self, struct sym_table* global);
void compiler_free(struct compiler* self);
int compiler_compile(struct compiler* self,
@ -36,4 +36,7 @@ size_t compiler_gen_instr(struct compiler* self,
enum Opcodes op,
int param);
size_t compiler_get_type(struct compiler* self,
struct node* node,
struct type* type);
#endif

View File

@ -430,7 +430,31 @@ int lexer_scan_string(struct lexer* self,
break;
}
value[sz++] = self->source[cursor++];
if (cursor + 1 < strlen(self->source)
&& self->source[cursor] == '\\')
{
char val = self->source[cursor + 1];
switch (val)
{
case 'n': value[sz++] = '\n'; break;
case 'r': value[sz++] = '\r'; break;
case 't': value[sz++] = '\t'; break;
case '\'': value[sz++] = '\''; break;
case '"': value[sz++] = '"'; break;
case '\\': value[sz++] = '\\'; break;
default:
fprintf(stderr, "unknown escaped char '%c'\n", val);
abort();
}
cursor += 2;
}
else
{
value[sz++] = self->source[cursor++];
}
}
if (found)

274
lang/src/native.c Normal file
View File

@ -0,0 +1,274 @@
#include "native.h"
#include "commons.h"
#include "type.h"
#include "value.h"
void native_init(struct native* self, native_fun_t fun)
{
assert(self);
assert(fun);
self->fun = fun;
}
void native_free(struct native* self)
{
assert(self);
}
void populate_native(struct vec* natives, struct sym_table* table)
{
struct type* ty;
// IO
// ==
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_VOID);
type_add_subtype(ty, TYPE_STRING);
populate_add_native(natives, table, "println", ty, fun_println);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_VOID);
type_add_subtype(ty, TYPE_STRING);
populate_add_native(natives, table, "print", ty, fun_print);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_STRING);
populate_add_native(natives, table, "readln", ty, fun_readln);
// CAST
// ====
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_STRING);
type_add_subtype(ty, TYPE_INT);
populate_add_native(natives, table, "itos", ty, fun_itos);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_FLOAT);
type_add_subtype(ty, TYPE_INT);
populate_add_native(natives, table, "itof", ty, fun_itof);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_STRING);
type_add_subtype(ty, TYPE_FLOAT);
populate_add_native(natives, table, "ftos", ty, fun_ftos);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_INT);
type_add_subtype(ty, TYPE_FLOAT);
populate_add_native(natives, table, "ftoi", ty, fun_ftoi);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_INT);
type_add_subtype(ty, TYPE_STRING);
populate_add_native(natives, table, "stoi", ty, fun_stoi);
ty = malloc(sizeof(struct type));
type_init(ty, TYPE_FUN);
type_add_subtype(ty, TYPE_FLOAT);
type_add_subtype(ty, TYPE_STRING);
populate_add_native(natives, table, "stof", ty, fun_stof);
}
void populate_add_native(struct vec* natives,
struct sym_table* table,
char* name,
struct type* type,
native_fun_t fun)
{
assert(natives);
assert(table);
assert(type);
sym_table_declare_global(table, name, type, natives->size);
struct value* val = malloc(sizeof(struct value));
value_init_new_native(val, fun, type, 0);
vec_push(natives, val);
}
struct value* fun_println(struct vec* args)
{
struct value* arg = args->data[0];
printf("%s\n", arg->data.s);
return NULL;
}
struct value* fun_print(struct vec* args)
{
struct value* arg = args->data[0];
printf("%s", arg->data.s);
return NULL;
}
struct value* fun_readln(struct vec* args)
{
(void) args;
char* input = NULL;
size_t len = 0;
getline(&input, &len, stdin);
struct value* val = malloc(sizeof(struct value));
value_init_string(val, input, 0);
free(input);
return val;
}
// CAST
// ====
struct value* fun_itos(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
char str[GUX_STR_SIZE];
memset(str, 0, GUX_STR_SIZE);
snprintf(str, GUX_STR_SIZE, "%d", value->data.i);
struct value* result = malloc(sizeof(struct value));
value_init_string(result, str, value->line);
return result;
}
struct value* fun_itof(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
struct value* result = malloc(sizeof(struct value));
value_init_float(result, (float) value->data.i, value->line);
return result;
}
struct value* fun_ftos(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
char str[GUX_STR_SIZE];
memset(str, 0, GUX_STR_SIZE);
snprintf(str, GUX_STR_SIZE, "%f", value->data.f);
struct value* result = malloc(sizeof(struct value));
value_init_string(result, str, value->line);
return result;
}
struct value* fun_ftoi(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
struct value* result = malloc(sizeof(struct value));
value_init_int(result, (int) value->data.f, value->line);
return result;
}
struct value* fun_stoi(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
char* str = value->data.s;
int res = 0;
size_t k = 0;
size_t const N = strlen(str);
while (k < N && isspace(str[k]))
{
k++;
}
int neg = 0;
if (k < N && str[k] == '-')
{
k++;
neg = 1;
}
while (k < N && isdigit(str[k]))
{
res *= 10;
res += (str[k] - '0');
k++;
}
struct value* result = malloc(sizeof(struct value));
value_init_int(result, neg ? -res : res, value->line);
return result;
}
struct value* fun_stof(struct vec* args)
{
assert(args);
struct value* value = args->data[0];
char* str = value->data.s;
float res = 0.0f;
size_t k = 0;
size_t const N = strlen(str);
while (k < N && isspace(str[k]))
{
k++;
}
int neg = 0;
if (k < N && str[k] == '-')
{
k++;
neg = 1;
}
while (k < N && isdigit(str[k]))
{
res *= 10;
res += (str[k] - '0');
k++;
}
if (k < N && str[k] == '.')
{
k++;
}
float power = 0.0f;
while (k < N && isdigit(str[k]))
{
res *= 10;
power++;
res += (str[k] - '0');
k++;
}
res /= powf(10.0f, power);
struct value* result = malloc(sizeof(struct value));
value_init_float(result, neg ? -res : res, value->line);
return result;
}

40
lang/src/native.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef NATIVE_H
#define NATIVE_H
#include <commons.h>
#include "sym_table.h"
typedef struct value* (*native_fun_t)(struct vec*);
struct native {
native_fun_t fun;
};
void native_init(struct native* self, native_fun_t fun);
void native_free(struct native* self);
void populate_native(struct vec* natives, struct sym_table* table);
void populate_add_native(struct vec* natives,
struct sym_table* table,
char* name,
struct type* type,
native_fun_t fun);
// IO
// ==
struct value* fun_println(struct vec* args);
struct value* fun_print(struct vec* args);
struct value* fun_readln(struct vec* args);
// CAST
// ====
struct value* fun_itos(struct vec* args);
struct value* fun_itof(struct vec* args);
struct value* fun_ftos(struct vec* args);
struct value* fun_ftoi(struct vec* args);
struct value* fun_stoi(struct vec* args);
struct value* fun_stof(struct vec* args);
#endif

View File

@ -6,7 +6,7 @@
G(OP_BRT), G(OP_NOP), G(OP_NOT), G(OP_EQ), \
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), G(OP_MOD), G(OP_POW), \
G(OP_LT), G(OP_LE), G(OP_GT),G(OP_GE), G(OP_LOAD), G(OP_STORE), \
G(OP_SWAP), G(OP_CALL), G(OP_RET)
G(OP_SWAP), G(OP_CALL), G(OP_RET), G(OP_GLOAD)
#include <commons.h>

View File

@ -459,6 +459,7 @@ struct node* parser_try_new_params(struct parser* self)
node->children.data[idx] = node_new_clone(type);
}
vec_free_elements(&types);
vec_free(&types);
vec_init(&types, 1);
}

View File

@ -1,13 +1,16 @@
#include "sym_table.h"
#include "commons.h"
#include "vec.h"
void sym_table_init(struct sym_table* self)
void sym_table_init(struct sym_table* self, struct sym_table* prev)
{
assert(self);
self->root = NULL;
sym_table_push_table(self);
self->addr_counter = 0;
self->prev = prev;
}
void sym_table_free(struct sym_table* self)
@ -87,6 +90,11 @@ struct sym* sym_table_try_by_name(struct sym_table* self, char* const name)
table = table->prev;
}
if (self->prev)
{
return sym_table_try_by_name(self->prev, name);
}
return NULL;
}
@ -124,6 +132,7 @@ int sym_table_declare(struct sym_table* self,
sym->name = strdup(name);
sym->type = new_type;
sym->parent = self->root;
sym->is_global = 0;
sym->is_var = is_var;
sym->addr = self->addr_counter;
vec_push(&table->syms, sym);
@ -133,6 +142,34 @@ int sym_table_declare(struct sym_table* self,
return 0;
}
int sym_table_declare_global(struct sym_table* self,
char* const name,
struct type* new_type,
int addr)
{
assert(self);
assert(strcmp(name, "") != 0);
struct sym* s = sym_table_try_by_name(self, name);
if (s && s->parent == self->root && s->is_global)
{
return 1;
}
struct table* table = self->root;
struct sym* sym = malloc(sizeof(struct sym));
sym->name = strdup(name);
sym->type = new_type;
sym->parent = self->root;
sym->is_global = 1;
sym->is_var = 0;
sym->addr = addr;
vec_push(&table->syms, sym);
return 0;
}
size_t sym_table_str(struct sym_table* self, char* buffer, size_t size)
{
assert(self);
@ -147,9 +184,12 @@ size_t sym_table_str(struct sym_table* self, char* buffer, size_t size)
for (size_t i=0; i<table->syms.size; i++)
{
struct sym* sym = table->syms.data[i];
char type[GUX_STR_SIZE];
type_str(sym->type, type, GUX_STR_SIZE);
sz += snprintf(buffer + sz, size - sz,
"[%s::%p] -> %d\n",
sym->name, sym->parent, sym->addr);
"[%s::%p, %s] -> %d\n",
sym->name, sym->parent, type, sym->addr);
}
return sz;

View File

@ -9,6 +9,7 @@ struct sym {
struct table* parent;
char* name;
int is_var;
int is_global;
int addr;
struct type* type;
};
@ -19,11 +20,12 @@ struct table {
};
struct sym_table {
struct sym_table* prev;
struct table* root;
int addr_counter;
};
void sym_table_init(struct sym_table* self);
void sym_table_init(struct sym_table* self, struct sym_table* prev);
void sym_table_free(struct sym_table* self);
void sym_table_push_table(struct sym_table* self);
@ -43,6 +45,11 @@ int sym_table_declare(struct sym_table* self,
struct type* new_type,
int is_var);
int sym_table_declare_global(struct sym_table* self,
char* const name,
struct type* new_type,
int addr);
size_t sym_table_str(struct sym_table* self, char* buffer, size_t size);
#endif

View File

@ -6,10 +6,10 @@
#include "type_resolver.h"
#include "fun.h"
void type_checker_init(struct type_checker* self)
void type_checker_init(struct type_checker* self, struct sym_table* global)
{
assert(self);
sym_table_init(&self->sym_table);
sym_table_init(&self->sym_table, global);
type_resolver_init(&self->resolver, &self->sym_table);
memset(self->error_msg, 0, GUX_STR_SIZE);
vec_init(&self->fun_stack, 1);
@ -81,7 +81,6 @@ int type_checker_check(struct type_checker* self,
case NODE_CALL: {
struct node* target = node->children.data[0];
struct node* args = node->children.data[1];
struct sym* entry = sym_table_try_by_name(&self->sym_table,
target->value);
@ -96,6 +95,7 @@ int type_checker_check(struct type_checker* self,
struct type* ty = entry->type;
assert(ty);
if (ty->subtypes.size - 1 != args->children.size)
{
self->error_line = node->line;
@ -104,6 +104,29 @@ int type_checker_check(struct type_checker* self,
return 1;
}
for (size_t i=0; i<args->children.size; i++)
{
struct type* sub = ty->subtypes.data[i + 1];
struct node* sub_node = args->children.data[i];
struct type t;
type_init(&t, TYPE_VOID);
if (type_resolver_resolve(&self->resolver, sub_node, &t) != 0)
{
type_free(&t);
return 1;
}
if (!type_equals(&t, sub))
{
type_checker_error_msg(self, sub_node, sub, &t);
type_free(&t);
return 1;
}
type_free(&t);
}
} return 0;
case NODE_FUN: {
@ -463,7 +486,10 @@ int type_checker_check(struct type_checker* self,
} return 0;
case NODE_ASSERT:
case NODE_ASSERT: {
return type_checker_check(self, node->children.data[0]);
} return 0;
case NODE_NOT:
case NODE_AND:
case NODE_OR: {
@ -480,6 +506,16 @@ int type_checker_check(struct type_checker* self,
case NODE_EQ:
case NODE_NE: {
for (size_t i=1; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
if ( type_checker_check(self, child) != 0 )
{
return 1;
}
}
struct type type;
type_init(&type, TYPE_VOID);
type_resolver_resolve(&self->resolver, node->children.data[0], &type);

View File

@ -14,7 +14,7 @@ struct type_checker {
struct vec fun_stack;
};
void type_checker_init(struct type_checker* self);
void type_checker_init(struct type_checker* self, struct sym_table* global);
void type_checker_free(struct type_checker* self);
int type_checker_check(struct type_checker* self,

View File

@ -1,4 +1,5 @@
#include "value.h"
#include "native.h"
#include "type.h"
#include "fun.h"
@ -9,6 +10,7 @@ void value_init_bool(struct value* self, int value, int line)
type_init(&self->type, TYPE_BOOL);
self->data.b = value;
self->line = line;
self->is_native = 0;
}
void value_init_int(struct value* self, int value, int line)
@ -18,6 +20,7 @@ void value_init_int(struct value* self, int value, int line)
type_init(&self->type, TYPE_INT);
self->data.i = value;
self->line = line;
self->is_native = 0;
}
@ -28,15 +31,17 @@ void value_init_float(struct value* self, float value, int line)
type_init(&self->type, TYPE_FLOAT);
self->data.f = value;
self->line = line;
self->is_native = 0;
}
void value_init_string(struct value* self, char* value, int line)
{
assert(self);
assert(value);
type_init(&self->type, TYPE_STRING);
self->data.s = strdup(value);
self->line = line;
self->is_native = 0;
}
void value_init_new_fun(struct value* self, struct fun* value, int line)
@ -46,6 +51,19 @@ void value_init_new_fun(struct value* self, struct fun* value, int line)
type_init_from_node(&self->type, value->node);
self->data.fun = value;
self->line = line;
self->is_native = 0;
}
void value_init_new_native(struct value* self, native_fun_t native,
struct type* type, int line)
{
assert(self);
type_init(&self->type, TYPE_FUN);
type_copy(type, &self->type);
self->data.native = native;
self->line = line;
self->is_native = 1;
}
void value_free(struct value* self)
@ -56,7 +74,7 @@ void value_free(struct value* self)
{
free(self->data.s);
}
else if (self->type.kind == TYPE_FUN)
else if (self->type.kind == TYPE_FUN && !self->is_native)
{
fun_free(self->data.fun);
free(self->data.fun);
@ -68,17 +86,24 @@ void value_free(struct value* self)
struct value* value_new_clone(struct value* self)
{
assert(self);
struct value* clone = malloc(sizeof(struct value));
type_init(&clone->type, TYPE_VOID);
type_copy(&self->type, &clone->type);
clone->data = self->data;
clone->is_native = self->is_native;
if (clone->type.kind == TYPE_FUN)
if (clone->type.kind == TYPE_FUN && !self->is_native)
{
clone->data.fun = fun_new_clone(self->data.fun);
}
if (clone->type.kind == TYPE_STRING)
{
clone->data.s = strdup(self->data.s);
}
return clone;
}

View File

@ -3,6 +3,7 @@
#include <commons.h>
#include <type.h>
#include "native.h"
#define VAL_TRUE 1
#define VAL_FALSE 0
@ -13,11 +14,13 @@ union value_data {
float f;
int i;
struct fun* fun;
native_fun_t native;
};
struct value {
struct type type;
int line;
int is_native;
union value_data data;
};
@ -26,6 +29,8 @@ void value_init_int(struct value* self, int value, int line);
void value_init_float(struct value* self, float value, int line);
void value_init_string(struct value* self, char* value, int line);
void value_init_new_fun(struct value* self, struct fun* value, int line);
void value_init_new_native(struct value* self, native_fun_t native,
struct type* type, int line);
void value_free(struct value* self);

View File

@ -85,7 +85,16 @@ Test(lexer, string) {
test_lexer("'hello world ' \" bim\" '\\\"hello\\\"'", 3,
"STRING[hello world ]",
"STRING[ bim]",
"STRING[\\\"hello\\\"]");
"STRING[\"hello\"]");
test_lexer("' \\'coucou\\' '", 1,
"STRING[ 'coucou' ]");
test_lexer("' \\'cou\\ncou\\' '", 1,
"STRING[ 'cou\ncou' ]");
test_lexer("' \\'cou\\r\\tcou\\' '", 1,
"STRING[ 'cou\r\tcou' ]");
}
Test(lexer, arithemtic) {

View File

@ -4,7 +4,7 @@
Test(sym_table, simple) {
struct sym_table table;
sym_table_init(&table);
sym_table_init(&table, NULL);
struct sym* sym = sym_table_try_by_name(&table, "hello");
cr_assert_eq(sym, 0);
@ -24,7 +24,7 @@ Test(sym_table, simple) {
Test(sym_table, already_exists) {
struct sym_table table;
sym_table_init(&table);
sym_table_init(&table, NULL);
struct type* ty = malloc(sizeof(struct type));
type_init(ty, TYPE_INT);
@ -40,7 +40,7 @@ Test(sym_table, already_exists) {
Test(sym_table, scope) {
struct sym_table table;
sym_table_init(&table);
sym_table_init(&table, NULL);
struct type* ty_int = malloc(sizeof(struct type));
type_init(ty_int, TYPE_INT);
@ -74,7 +74,7 @@ Test(sym_table, scope) {
Test(sym_table, outer_scope) {
struct sym_table table;
sym_table_init(&table);
sym_table_init(&table, NULL);
struct type* ty_int = malloc(sizeof(struct type));
type_init(ty_int, TYPE_INT);

View File

@ -14,7 +14,7 @@ static void test_check_ok(char const* source)
cr_assert_neq(ast, NULL);
struct type_checker tc;
type_checker_init(&tc);
type_checker_init(&tc, NULL);
char buf[GUX_STR_SIZE];
node_str(ast, buf, GUX_STR_SIZE);
@ -38,7 +38,7 @@ static void test_check_ko(char const* source)
cr_assert_neq(ast, NULL, "cannot parse: %s", source);
struct type_checker tc;
type_checker_init(&tc);
type_checker_init(&tc, NULL);
cr_assert_neq(type_checker_check(&tc, ast), 0,
"%s shouldn't pass check test", source);

23
tests/cast.gux Normal file
View File

@ -0,0 +1,23 @@
# from int
# --------
assert 37.0 == itof(37);
assert '37' == itos(37);
# from float
# ----------
assert 2 == ftoi(2.8);
assert '3.100000' == ftos(3.1);
# from string
# -----------
assert 128 == stoi('128');
assert 328 == stoi(' 328 ');
assert 24 == stoi(' 24 7 ');
assert -34 == stoi('-34');
assert -34 == stoi(' -34 ');
assert 0 == stoi('abc');
assert 2.4 == stof('2.4');
assert -2.4 == stof('-2.4');
assert 322.4 == stof(' 322.4 ');
assert -2.4 == stof(' -2.4 ');

View File

@ -6,11 +6,12 @@
#include "vec.h"
#include "fun.h"
void vm_init(struct vm* self)
void vm_init(struct vm* self, struct vec* natives)
{
assert(self);
self->pc = 0;
self->fp = 0;
self->natives = natives;
self->error_line = 0;
memset(self->error_msg, 0, GUX_STR_SIZE);
@ -133,7 +134,6 @@ int vm_exec(struct vm* self, struct program* program)
case OP_CALL: {
int fun_addr = vm_pop(self);
struct value* fun_val = program->constant_pool.data[fun_addr];
struct fun* fun = fun_val->data.fun;
struct vec args;
vec_init(&args, 1);
@ -145,9 +145,38 @@ int vm_exec(struct vm* self, struct program* program)
vec_push(&args, addr);
}
if (fun_val->is_native)
{
native_fun_t fun = fun_val->data.native;
struct vec fun_args;
vec_init(&fun_args, 1);
for (size_t i=0; i<args.size; i++)
{
int addr = *(int*)args.data[i];
vec_push(&fun_args, program->constant_pool.data[addr]);
}
struct value* res = fun(&fun_args);
if (res)
{
vm_push(self, program_push_constant(program, res));
}
vec_free(&fun_args);
vec_free_elements(&args);
vec_free(&args);
self->pc++;
break;
}
vm_add_frame(self);
struct frame* my_frame = self->stack[self->fp - 1];
struct fun* fun = fun_val->data.fun;
for (size_t i=0; i<args.size; i++)
{
size_t k = args.size - 1 - i;
@ -203,6 +232,17 @@ int vm_exec(struct vm* self, struct program* program)
self->pc++;
} break;
case OP_GLOAD: {
struct value* value = self->natives->data[param];
size_t addr =
program_push_constant(program, value_new_clone(value));
vm_push(self, addr);
self->pc++;
} break;
case OP_LOAD: {
int stack_addr = vm_load(self, param);
struct frame* myframe = self->stack[self->fp - 1];

View File

@ -25,9 +25,10 @@ struct vm {
size_t pc;
size_t fp;
struct frame* stack[FRAME_DEPTH];
struct vec* natives;
};
void vm_init(struct vm* self);
void vm_init(struct vm* self, struct vec* natives);
void vm_free(struct vm* self);
void vm_add_frame(struct vm* self);
void vm_remove_frame(struct vm* self);