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 <compiler.h>
#include <vm.h> #include <vm.h>
#include <sym_table.h> #include <sym_table.h>
#include <native.h>
char* load_new_source(char const* path) char* load_new_source(char const* path)
{ {
@ -159,8 +160,16 @@ int main(int argc, char** argv)
printf("%s\n", msg); 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; struct type_checker checker;
type_checker_init(&checker); type_checker_init(&checker, &globals);
if (type_checker_check(&checker, ast) != 0) if (type_checker_check(&checker, ast) != 0)
{ {
@ -171,6 +180,12 @@ int main(int argc, char** argv)
type_checker_free(&checker); 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) if (ast)
{ {
node_free(ast); node_free(ast);
@ -196,7 +211,7 @@ int main(int argc, char** argv)
program_init(&program); program_init(&program);
struct compiler compiler; struct compiler compiler;
compiler_init(&compiler); compiler_init(&compiler, &globals);
if (compiler_compile(&compiler, ast, &program) != 0) if (compiler_compile(&compiler, ast, &program) != 0)
{ {
@ -209,6 +224,12 @@ int main(int argc, char** argv)
program_free(&program); program_free(&program);
type_checker_free(&checker); 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) if (ast)
{ {
@ -246,7 +267,7 @@ int main(int argc, char** argv)
} }
struct vm vm; struct vm vm;
vm_init(&vm); vm_init(&vm, &natives);
err = vm_exec(&vm, &program); err = vm_exec(&vm, &program);
@ -262,6 +283,12 @@ int main(int argc, char** argv)
compiler_free(&compiler); compiler_free(&compiler);
program_free(&program); program_free(&program);
type_checker_free(&checker); 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) if (ast)
{ {
@ -297,6 +324,12 @@ int main(int argc, char** argv)
compiler_free(&compiler); compiler_free(&compiler);
program_free(&program); program_free(&program);
type_checker_free(&checker); 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) if (ast)
{ {

View File

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

View File

@ -6,14 +6,15 @@
#include "sym_table.h" #include "sym_table.h"
#include "type.h" #include "type.h"
#include "type_checker.h" #include "type_checker.h"
#include "type_resolver.h"
#include "value.h" #include "value.h"
#include "vec.h" #include "vec.h"
#include "fun.h" #include "fun.h"
void compiler_init(struct compiler* self) void compiler_init(struct compiler* self, struct sym_table* global)
{ {
assert(self); assert(self);
sym_table_init(&self->sym_table); sym_table_init(&self->sym_table, global);
memset(self->error_msg, 0, GUX_STR_SIZE); memset(self->error_msg, 0, GUX_STR_SIZE);
self->stack_size = 0; self->stack_size = 0;
vec_init(&self->loops, 1); vec_init(&self->loops, 1);
@ -55,7 +56,7 @@ int compiler_compile(struct compiler* self,
sym_table_push_table(&self->sym_table); sym_table_push_table(&self->sym_table);
struct compiler compiler; struct compiler compiler;
compiler_init(&compiler); compiler_init(&compiler, self->sym_table.prev);
struct vec idents; struct vec idents;
vec_init(&idents, 1); vec_init(&idents, 1);
@ -75,7 +76,7 @@ int compiler_compile(struct compiler* self,
struct node* ident = idents.data[j]; struct node* ident = idents.data[j];
struct type* ty = malloc(sizeof(struct type)); 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, sym_table_declare_const(&compiler.sym_table,
ident->value, ident->value,
@ -129,7 +130,15 @@ int compiler_compile(struct compiler* self,
assert(entry); 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); compiler_gen_instr(self, program, OP_CALL, args->children.size);
} break; } break;
@ -261,7 +270,14 @@ int compiler_compile(struct compiler* self,
return 1; 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; } break;
case NODE_CONSTDECL: case NODE_CONSTDECL:
@ -278,7 +294,8 @@ int compiler_compile(struct compiler* self,
} }
struct type* ty = malloc(sizeof(struct type)); 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, sym_table_declare(&self->sym_table, node->value, ty,
node->type == NODE_VARDECL); node->type == NODE_VARDECL);
@ -315,6 +332,7 @@ int compiler_compile(struct compiler* self,
case NODE_STRING: { case NODE_STRING: {
struct value* val = malloc(sizeof(struct value)); struct value* val = malloc(sizeof(struct value));
value_init_string(val, node->value, node->line); value_init_string(val, node->value, node->line);
size_t addr = program_push_constant(program, val); size_t addr = program_push_constant(program, val);
compiler_gen_instr(self, program, OP_PUSH, addr); 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_CALL: break;
case OP_LOAD: case OP_LOAD:
case OP_GLOAD:
case OP_PUSH: self->stack_size += 1; break; case OP_PUSH: self->stack_size += 1; break;
case OP_LT: case OP_LT:
@ -627,3 +646,14 @@ size_t compiler_gen_instr(struct compiler* self,
return addr; 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; 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); void compiler_free(struct compiler* self);
int compiler_compile(struct compiler* self, int compiler_compile(struct compiler* self,
@ -36,4 +36,7 @@ size_t compiler_gen_instr(struct compiler* self,
enum Opcodes op, enum Opcodes op,
int param); int param);
size_t compiler_get_type(struct compiler* self,
struct node* node,
struct type* type);
#endif #endif

View File

@ -430,7 +430,31 @@ int lexer_scan_string(struct lexer* self,
break; 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) 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_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_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_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> #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); node->children.data[idx] = node_new_clone(type);
} }
vec_free_elements(&types);
vec_free(&types); vec_free(&types);
vec_init(&types, 1); vec_init(&types, 1);
} }

View File

@ -1,13 +1,16 @@
#include "sym_table.h" #include "sym_table.h"
#include "commons.h"
#include "vec.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); assert(self);
self->root = NULL; self->root = NULL;
sym_table_push_table(self); sym_table_push_table(self);
self->addr_counter = 0; self->addr_counter = 0;
self->prev = prev;
} }
void sym_table_free(struct sym_table* self) 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; table = table->prev;
} }
if (self->prev)
{
return sym_table_try_by_name(self->prev, name);
}
return NULL; return NULL;
} }
@ -124,6 +132,7 @@ int sym_table_declare(struct sym_table* self,
sym->name = strdup(name); sym->name = strdup(name);
sym->type = new_type; sym->type = new_type;
sym->parent = self->root; sym->parent = self->root;
sym->is_global = 0;
sym->is_var = is_var; sym->is_var = is_var;
sym->addr = self->addr_counter; sym->addr = self->addr_counter;
vec_push(&table->syms, sym); vec_push(&table->syms, sym);
@ -133,6 +142,34 @@ int sym_table_declare(struct sym_table* self,
return 0; 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) size_t sym_table_str(struct sym_table* self, char* buffer, size_t size)
{ {
assert(self); 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++) for (size_t i=0; i<table->syms.size; i++)
{ {
struct sym* sym = table->syms.data[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, sz += snprintf(buffer + sz, size - sz,
"[%s::%p] -> %d\n", "[%s::%p, %s] -> %d\n",
sym->name, sym->parent, sym->addr); sym->name, sym->parent, type, sym->addr);
} }
return sz; return sz;

View File

@ -9,6 +9,7 @@ struct sym {
struct table* parent; struct table* parent;
char* name; char* name;
int is_var; int is_var;
int is_global;
int addr; int addr;
struct type* type; struct type* type;
}; };
@ -19,11 +20,12 @@ struct table {
}; };
struct sym_table { struct sym_table {
struct sym_table* prev;
struct table* root; struct table* root;
int addr_counter; 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_free(struct sym_table* self);
void sym_table_push_table(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, struct type* new_type,
int is_var); 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); size_t sym_table_str(struct sym_table* self, char* buffer, size_t size);
#endif #endif

View File

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

View File

@ -14,7 +14,7 @@ struct type_checker {
struct vec fun_stack; 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); void type_checker_free(struct type_checker* self);
int type_checker_check(struct type_checker* self, int type_checker_check(struct type_checker* self,

View File

@ -1,4 +1,5 @@
#include "value.h" #include "value.h"
#include "native.h"
#include "type.h" #include "type.h"
#include "fun.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); type_init(&self->type, TYPE_BOOL);
self->data.b = value; self->data.b = value;
self->line = line; self->line = line;
self->is_native = 0;
} }
void value_init_int(struct value* self, int value, int line) 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); type_init(&self->type, TYPE_INT);
self->data.i = value; self->data.i = value;
self->line = line; 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); type_init(&self->type, TYPE_FLOAT);
self->data.f = value; self->data.f = value;
self->line = line; self->line = line;
self->is_native = 0;
} }
void value_init_string(struct value* self, char* value, int line) void value_init_string(struct value* self, char* value, int line)
{ {
assert(self); assert(self);
assert(value);
type_init(&self->type, TYPE_STRING); type_init(&self->type, TYPE_STRING);
self->data.s = strdup(value); self->data.s = strdup(value);
self->line = line; self->line = line;
self->is_native = 0;
} }
void value_init_new_fun(struct value* self, struct fun* value, int line) 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); type_init_from_node(&self->type, value->node);
self->data.fun = value; self->data.fun = value;
self->line = line; 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) void value_free(struct value* self)
@ -56,7 +74,7 @@ void value_free(struct value* self)
{ {
free(self->data.s); 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); fun_free(self->data.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) struct value* value_new_clone(struct value* self)
{ {
assert(self); assert(self);
struct value* clone = malloc(sizeof(struct value)); struct value* clone = malloc(sizeof(struct value));
type_init(&clone->type, TYPE_VOID); type_init(&clone->type, TYPE_VOID);
type_copy(&self->type, &clone->type); type_copy(&self->type, &clone->type);
clone->data = self->data; 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); clone->data.fun = fun_new_clone(self->data.fun);
} }
if (clone->type.kind == TYPE_STRING)
{
clone->data.s = strdup(self->data.s);
}
return clone; return clone;
} }

View File

@ -3,6 +3,7 @@
#include <commons.h> #include <commons.h>
#include <type.h> #include <type.h>
#include "native.h"
#define VAL_TRUE 1 #define VAL_TRUE 1
#define VAL_FALSE 0 #define VAL_FALSE 0
@ -13,11 +14,13 @@ union value_data {
float f; float f;
int i; int i;
struct fun* fun; struct fun* fun;
native_fun_t native;
}; };
struct value { struct value {
struct type type; struct type type;
int line; int line;
int is_native;
union value_data data; 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_float(struct value* self, float value, int line);
void value_init_string(struct value* self, char* 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_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); void value_free(struct value* self);

View File

@ -85,7 +85,16 @@ Test(lexer, string) {
test_lexer("'hello world ' \" bim\" '\\\"hello\\\"'", 3, test_lexer("'hello world ' \" bim\" '\\\"hello\\\"'", 3,
"STRING[hello world ]", "STRING[hello world ]",
"STRING[ bim]", "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) { Test(lexer, arithemtic) {

View File

@ -4,7 +4,7 @@
Test(sym_table, simple) { Test(sym_table, simple) {
struct sym_table table; struct sym_table table;
sym_table_init(&table); sym_table_init(&table, NULL);
struct sym* sym = sym_table_try_by_name(&table, "hello"); struct sym* sym = sym_table_try_by_name(&table, "hello");
cr_assert_eq(sym, 0); cr_assert_eq(sym, 0);
@ -24,7 +24,7 @@ Test(sym_table, simple) {
Test(sym_table, already_exists) { Test(sym_table, already_exists) {
struct sym_table table; struct sym_table table;
sym_table_init(&table); sym_table_init(&table, NULL);
struct type* ty = malloc(sizeof(struct type)); struct type* ty = malloc(sizeof(struct type));
type_init(ty, TYPE_INT); type_init(ty, TYPE_INT);
@ -40,7 +40,7 @@ Test(sym_table, already_exists) {
Test(sym_table, scope) { Test(sym_table, scope) {
struct sym_table table; struct sym_table table;
sym_table_init(&table); sym_table_init(&table, NULL);
struct type* ty_int = malloc(sizeof(struct type)); struct type* ty_int = malloc(sizeof(struct type));
type_init(ty_int, TYPE_INT); type_init(ty_int, TYPE_INT);
@ -74,7 +74,7 @@ Test(sym_table, scope) {
Test(sym_table, outer_scope) { Test(sym_table, outer_scope) {
struct sym_table table; struct sym_table table;
sym_table_init(&table); sym_table_init(&table, NULL);
struct type* ty_int = malloc(sizeof(struct type)); struct type* ty_int = malloc(sizeof(struct type));
type_init(ty_int, TYPE_INT); 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); cr_assert_neq(ast, NULL);
struct type_checker tc; struct type_checker tc;
type_checker_init(&tc); type_checker_init(&tc, NULL);
char buf[GUX_STR_SIZE]; char buf[GUX_STR_SIZE];
node_str(ast, 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); cr_assert_neq(ast, NULL, "cannot parse: %s", source);
struct type_checker tc; struct type_checker tc;
type_checker_init(&tc); type_checker_init(&tc, NULL);
cr_assert_neq(type_checker_check(&tc, ast), 0, cr_assert_neq(type_checker_check(&tc, ast), 0,
"%s shouldn't pass check test", source); "%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 "vec.h"
#include "fun.h" #include "fun.h"
void vm_init(struct vm* self) void vm_init(struct vm* self, struct vec* natives)
{ {
assert(self); assert(self);
self->pc = 0; self->pc = 0;
self->fp = 0; self->fp = 0;
self->natives = natives;
self->error_line = 0; self->error_line = 0;
memset(self->error_msg, 0, GUX_STR_SIZE); memset(self->error_msg, 0, GUX_STR_SIZE);
@ -133,7 +134,6 @@ int vm_exec(struct vm* self, struct program* program)
case OP_CALL: { case OP_CALL: {
int fun_addr = vm_pop(self); int fun_addr = vm_pop(self);
struct value* fun_val = program->constant_pool.data[fun_addr]; struct value* fun_val = program->constant_pool.data[fun_addr];
struct fun* fun = fun_val->data.fun;
struct vec args; struct vec args;
vec_init(&args, 1); vec_init(&args, 1);
@ -145,9 +145,38 @@ int vm_exec(struct vm* self, struct program* program)
vec_push(&args, addr); 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); vm_add_frame(self);
struct frame* my_frame = self->stack[self->fp - 1]; 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++) for (size_t i=0; i<args.size; i++)
{ {
size_t k = args.size - 1 - i; size_t k = args.size - 1 - i;
@ -203,6 +232,17 @@ int vm_exec(struct vm* self, struct program* program)
self->pc++; self->pc++;
} break; } 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: { case OP_LOAD: {
int stack_addr = vm_load(self, param); int stack_addr = vm_load(self, param);
struct frame* myframe = self->stack[self->fp - 1]; struct frame* myframe = self->stack[self->fp - 1];

View File

@ -25,9 +25,10 @@ struct vm {
size_t pc; size_t pc;
size_t fp; size_t fp;
struct frame* stack[FRAME_DEPTH]; 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_free(struct vm* self);
void vm_add_frame(struct vm* self); void vm_add_frame(struct vm* self);
void vm_remove_frame(struct vm* self); void vm_remove_frame(struct vm* self);