Merge jackywulf.com:Fcalva/flisp

This commit is contained in:
attilavs2 2025-03-26 11:40:30 +01:00
commit cb44634016
18 changed files with 289 additions and 113 deletions

View file

@ -3,7 +3,7 @@
OUTNAME = flisp OUTNAME = flisp
CFLAGS = -std=c99 -O0 -flto -Wall -Wextra -g -pipe -Wno-cast-function-type CFLAGS = -std=c99 -O3 -flto -Wall -Wextra -g -pipe -Wno-cast-function-type
CC = gcc CC = gcc

View file

@ -8,16 +8,17 @@ The code in examples/ is public domain
## Building ## Building
Pre-requisites: Pre-requisites:
- yacc - Bison
- lex - lex
- A C99 compiler - A C99 compiler
- GNU Make - GNU Make
### Unix ### Unix
Running `make` (or `gmake` for BSDs) should work on most Unix systems. Running `make` (or `gmake` for BSDs), maybe twice depending on your version of make,
should work on most Unix systems.
It produces an executable called `flisp.amd64` It produces an executable called `flisp.amd64`
### Windows ### Windows
To meet the previously mentionned pre-requisites, you need to use mingw. To meet the previously mentionned pre-requisites, you need to use mingw.
I recommend installing w64devkit, then compiling Bison and Flex from source. I recommend installing w64devkit, then compiling Bison and Flex from source.
Run `make win` Run `make win`, twice

View file

@ -1,13 +1,5 @@
tmp:
- fix realloc
- Benchmarks - Benchmarks
- Tests - Tests
- Rework assign/call to work better
- Finish internal allocator
- Strings
- String casts
- Core functions
- Type checks - Type checks
- Scopes - Scopes

3
dump.txt Normal file
View file

@ -0,0 +1,3 @@
build/interpreter.o: file format elf64-x86-64

BIN
perf.data Normal file

Binary file not shown.

View file

@ -76,8 +76,9 @@ typedef struct {
typedef struct { typedef struct {
uint is_array : 1; uint is_array : 1;
uint type : 15; uint is_strong : 1;
uint type : 14;
} PACKED Tag; } PACKED Tag;
@ -140,6 +141,7 @@ typedef Value (bi_fn_t)(void);
typedef struct { typedef struct {
Tag params[8]; Tag params[8];
Tag output;
i16 n_param; i16 n_param;
i16 is_builtin; i16 is_builtin;
union { union {

View file

@ -72,7 +72,8 @@ enum BuiltinStatements {
struct Statement { struct Statement {
i32 type; i32 type;
i32 is_const; // Statement is constant, != is a constant - TODO : implem i16 is_const; // Statement is constant, != is a constant - TODO : implem
i16 scope;
void **children; void **children;
i32 child_n; i32 child_n;
void *parent; void *parent;
@ -93,16 +94,21 @@ typedef struct Statement Statement;
// In practice, this is allocated in parse.c // In practice, this is allocated in parse.c
typedef struct { typedef struct {
// Kept for debug messages // Debug messages
// TODO
i32 curr_line; i32 curr_line;
i32 curr_column;
i32 max_statement; // Unused while parsing i32 scope_id;
i32 curr_statement; i32 curr_scope;
i32 scope_stack[256];
HashMap symbol_map; HashMap symbol_map;
i32 fn_n;
FnSig *funcs;
i32 stack_size; i32 stack_size;
i32 curr_statement;
Statement statements[]; Statement statements[];
} ASTStack; } ASTStack;

View file

@ -23,12 +23,12 @@
// 0 : None (still features runtime debug) // 0 : None (still features runtime debug)
// 1 : Some checks // 1 : Some checks
// 2 : All checks // 2 : All checks
#define DEBUG 2 #define DEBUG 0
// Debug logs // Debug logs
// 0 : None // 0 : None
// 1 : All misc debug logs // 1 : All misc debug logs
#define LOG 1 #define LOG 0
// TODO : Automate this // TODO : Automate this
#define INTERPR #define INTERPR

View file

@ -58,13 +58,11 @@ int evaluate(Value val){
case T_null: case T_null:
return 0; return 0;
case T_int: case T_int:
return val.v4B.value;
case T_fix: case T_fix:
return val.v4B.value; return val.v4B.value;
case T_float: case T_float:
return FL_EPSILON > fabs((float)val.v4B.value); return FL_EPSILON < fabs(val.v4B.vfl);
case T_str: case T_str:
return 0;
case T_fn: case T_fn:
return 0; return 0;
default: default:
@ -255,11 +253,13 @@ void print_ast(Statement *base){
Value str_to_val(char *str, i32 len){ Value str_to_val(char *str, i32 len){
if(len < 0) if(len < 0)
len = strlen(str); len = strlen(str);
if(len > 65536){
fprintf(stderr, "Warning : string is longer than 65k chars"
" - will be trunucated\n");
len = 65536;
}
Value retv; Value retv;
retv.tag = (Tag){.is_array = 0, .type = T_str}; retv.tag = (Tag){.is_array = 0, .type = T_str};
#if LOG
printf("str (%d) : %s\n", len, str);
#endif
if(len > 4){ if(len > 4){
u32 nstr = flisp_alloc(len); u32 nstr = flisp_alloc(len);
if(!nstr){ if(!nstr){
@ -278,15 +278,14 @@ Value str_to_val(char *str, i32 len){
} }
void clean_strval(Value str){ void clean_strval(Value str){
if(str.vstr.len < 5) if(str.vstr.len > 4)
return; flisp_free(str.vstr.pos);
flisp_free(str.vstr.pos);
} }
// Lesser special functions // Lesser special functions
Value is(Tag tag, Value b){ Value is(Tag tag, Value b){
Value ret = {.tag = {0,T_int}}; Value ret = {.tag = {0,0,T_int}};
ret.v4B.value = tag.is_array == b.tag.is_array && tag.type == b.tag.type; ret.v4B.value = tag.is_array == b.tag.is_array && tag.type == b.tag.type;
return ret; return ret;
} }
@ -414,7 +413,7 @@ cast_fn_t *cast_table[4][4] = {
}; };
Value cast(Tag type, Value b){ Value cast(Tag type, Value b){
if(type.type == b.tag.type) if(type.type == b.tag.type && type.is_array == b.tag.is_array)
return b; return b;
if(type.type == T_null || b.tag.type == T_null || type.type == T_fn if(type.type == T_null || b.tag.type == T_null || type.type == T_fn
|| b.tag.type == T_fn || type.is_array || b.tag.is_array){ || b.tag.type == T_fn || type.is_array || b.tag.is_array){
@ -573,31 +572,108 @@ Value sml(Value a, Value b){
} }
Value sml_eq(Value a, Value b){ Value sml_eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Sml_eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Sml_eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value <= b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl <= b.v4B.vfl;
break;
default:
runtime_err("Sml_eq : Invalid types");
}
return returnv;
} }
Value eq(Value a, Value b){ Value eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value == b.v4B.value;
break;
case T_float:
returnv.v4B.value = abs(a.v4B.vfl-b.v4B.vfl) > FL_EPSILON;
break;
default:
runtime_err("Eq : Invalid types");
}
return returnv;
} }
Value gt_eq(Value a, Value b){ Value gt_eq(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Gt_eq : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Gt_eq : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value >= b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl >= b.v4B.vfl;
break;
default:
runtime_err("Gt_eq : Invalid types");
}
return returnv;
} }
Value gt(Value a, Value b){ Value gt(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
if(a.tag.is_array || b.tag.is_array)
runtime_err("Gt : Invalid types");
if(a.tag.type != b.tag.type)
runtime_err("Gt : Types do not match");
switch(a.tag.type){
case T_int:
case T_fix:
returnv.v4B.value = a.v4B.value > b.v4B.value;
break;
case T_float:
returnv.v4B.value = a.v4B.vfl > b.v4B.vfl;
break;
default:
runtime_err("Gt : Invalid types");
}
return returnv;
} }
Value not(Value a){ Value not(Value a){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = !evaluate(a);
return returnv;
} }
Value and(Value a, Value b){ Value and(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = evaluate(a) && evaluate(b);
return returnv;
} }
Value or(Value a, Value b){ Value or(Value a, Value b){
Value returnv;
returnv.tag = (Tag){.is_array=0,.type=T_int};
returnv.v4B.value = evaluate(a) || evaluate(b);
return returnv;
} }
Value len(Value a){ Value len(Value a){
@ -647,43 +723,43 @@ Value fl_write(Value a){
default: default:
break; break;
} }
return (Value){.tag={0,T_null}}; return (Value){.tag={0,0,T_null}};
} }
Value nwline(){ Value nwline(){
printf("\n"); printf("\n");
return (Value){.tag={0,T_null}}; return (Value){.tag={0,0,T_null}};
} }
const Tag tany = {0,T_null}; const Tag tany = {0,0,T_any};
const Tag tint = {0,T_int}; const Tag tint = {0,0,T_int};
const Tag tfix = {0,T_fix}; const Tag tfix = {0,0,T_fix};
const Tag tfloat = {0,T_float}; const Tag tfloat = {0,0,T_float};
const Tag tstr = {0,T_str}; const Tag tstr = {0,0,T_str};
const Tag tfn = {0,T_fn}; const Tag tfn = {0,0,T_fn};
const Tag tvec = {1,T_null}; const Tag tvec = {1,0,T_any};
#define BICAST(x) ((bi_fn_t*)(x)) #define BICAST(x) ((bi_fn_t*)(x))
FnSig builtins[] = { FnSig builtins[] = {
{{tany,tany},2,1,{.bi = BICAST(add)}}, {{tany,tany},tany,2,1,{.bi = BICAST(add)}},
{{tany,tany},2,1,{.bi = BICAST(sub)}}, {{tany,tany},tany,2,1,{.bi = BICAST(sub)}},
{{tany,tany},2,1,{.bi = BICAST(mul)}}, {{tany,tany},tany,2,1,{.bi = BICAST(mul)}},
{{tany,tany},2,1,{.bi = BICAST(divv)}}, {{tany,tany},tany,2,1,{.bi = BICAST(divv)}},
{{tany,tany},2,1,{.bi = BICAST(mod)}}, {{tany,tany},tany,2,1,{.bi = BICAST(mod)}},
{{tany,tany},2,1,{.bi = BICAST(sml)}}, {{tany,tany},tint,2,1,{.bi = BICAST(sml)}},
{{tany,tany},2,1,{.bi = BICAST(sml_eq)}}, {{tany,tany},tint,2,1,{.bi = BICAST(sml_eq)}},
{{tany,tany},2,1,{.bi = BICAST(eq)}}, {{tany,tany},tint,2,1,{.bi = BICAST(eq)}},
{{tany,tany},2,1,{.bi = BICAST(gt_eq)}}, {{tany,tany},tint,2,1,{.bi = BICAST(gt_eq)}},
{{tany,tany},2,1,{.bi = BICAST(gt)}}, {{tany,tany},tint,2,1,{.bi = BICAST(gt)}},
{{tany} ,1,1,{.bi = BICAST(not)}}, {{tany} ,tint,1,1,{.bi = BICAST(not)}},
{{tany,tany},2,1,{.bi = BICAST(and)}}, {{tany,tany},tint,2,1,{.bi = BICAST(and)}},
{{tany,tany},2,1,{.bi = BICAST(or)}}, {{tany,tany},tint,2,1,{.bi = BICAST(or)}},
{{tvec} ,1,1,{.bi = BICAST(len)}}, {{tvec} ,tint,1,1,{.bi = BICAST(len)}},
{{tvec,tany},2,1,{.bi = BICAST(push)}}, {{tvec,tany},tany,2,1,{.bi = BICAST(push)}},
{{tvec,tint},2,1,{.bi = BICAST(pop)}}, {{tvec,tint},tany,2,1,{.bi = BICAST(pop)}},
{{tany} ,1,1,{.bi = BICAST(fl_write)}}, {{tany} ,tany,1,1,{.bi = BICAST(fl_write)}},
{{0} ,0,1,{.bi = BICAST(nwline)}} {{tany} ,tany,0,1,{.bi = BICAST(nwline)}}
}; };
char *bi_names[] = { char *bi_names[] = {
@ -708,7 +784,7 @@ char *bi_names[] = {
}; };
void symbol_map_add_bi(HashMap *map){ void symbol_map_add_bi(HashMap *map){
Tag fntag = {0,T_fn}; Tag fntag = {0,1,T_fn};
for(int i = BI_add; i < BI__end; i++){ for(int i = BI_add; i < BI__end; i++){
MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]); MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]);
ret->type = *((i16*)&fntag); ret->type = *((i16*)&fntag);

View file

@ -95,7 +95,7 @@ MapItem *hashmap_insert(HashMap *map, char *str){
if(!map->bit_free[hsh/32]){ if(!map->bit_free[hsh/32]){
map->buffer[hsh].hash = hsh; map->buffer[hsh].hash = hsh;
map->buffer[hsh].id = map->curr_id++; map->buffer[hsh].id = map->curr_id++;
strncpy(map->buffer[hsh].str, str, 32); strncpy(map->buffer[hsh].str, str, 36);
set_bit(map->bit_free, hsh); set_bit(map->bit_free, hsh);
map->item_n++; map->item_n++;
return &map->buffer[hsh]; return &map->buffer[hsh];
@ -117,7 +117,7 @@ MapItem *hashmap_insert(HashMap *map, char *str){
if(!taken){ if(!taken){
map->buffer[pos].hash = hsh; map->buffer[pos].hash = hsh;
map->buffer[pos].id = map->curr_id++; map->buffer[pos].id = map->curr_id++;
strncpy(map->buffer[pos].str, str, 32); strncpy(map->buffer[pos].str, str, 36);
set_bit(map->bit_free, hsh); set_bit(map->bit_free, hsh);
map->item_n++; map->item_n++;
return &map->buffer[pos]; return &map->buffer[pos];
@ -134,7 +134,7 @@ MapItem *hashmap_get(HashMap *map, char *str){
i32 c_hash = map->buffer[pos].hash; i32 c_hash = map->buffer[pos].hash;
match = c_hash == fhash; match = c_hash == fhash;
if(match) if(match)
match = !strncmp(str,map->buffer[pos].str,32); match = !strncmp(str,map->buffer[pos].str,36);
pos++; pos++;
} while(!match && pos < map->curr_len && pos-fhash < RELOCATE_TRY_MAX); } while(!match && pos < map->curr_len && pos-fhash < RELOCATE_TRY_MAX);
pos--; pos--;

View file

@ -31,11 +31,11 @@
typedef struct { typedef struct {
i32 hash; i32 hash;
char str[32]; char str[36];
i32 id; i32 id;
void *fnsig; void *fnsig;
i32 type; i16 type;
i32 is_const; i16 is_const;
} MapItem; } MapItem;

View file

@ -37,21 +37,19 @@ void assign(Value *dst, Value src){
#if LOG #if LOG
printf("Assign : %d -> %d\n", src.tag.type, dst->tag.type); printf("Assign : %d -> %d\n", src.tag.type, dst->tag.type);
#endif #endif
if((dst->tag.type == src.tag.type || dst->tag.type == T_any) if(dst->tag.is_array != src.tag.is_array)
&& dst->tag.is_array == src.tag.is_array){ runtime_err("Invalid assignement");
if(dst->tag.type == T_str) if(dst->tag.type == src.tag.type || !dst->tag.is_strong
clean_strval(*dst); || dst->tag.type == T_any)
*dst = src; *dst = src;
} }
else{ else{
fprintf(stderr, "Warning : Possibly incorrect assignement\n" runtime_err("Invalid assignement");
"This may error in the future\n");
*dst = src;
} }
} }
Value fncall(FnSig *fn, Statement **params){ Value fncall(FnSig *fn, Statement **params){
Value returnv = {.tag = {0, T_null}}; Value returnv = {.tag = {0,0,T_null}};
if(fn->is_builtin){ if(fn->is_builtin){
switch(fn->n_param){ switch(fn->n_param){
case 0: case 0:
@ -87,7 +85,7 @@ void init_exec(){
} }
Value execute(Statement *stat){ Value execute(Statement *stat){
Value returnv = {.tag = {0,T_null}}; Value returnv = {.tag = {0,0,T_null}};
switch(stat->type){ switch(stat->type){
case ST_Varuse: case ST_Varuse:
if(vars[stat->var_id].tag.type == T_fn){ if(vars[stat->var_id].tag.type == T_fn){

View file

@ -51,7 +51,7 @@ int main(int argc, char *argv[]){
} }
else { else {
printf("fLisp interactive env - v0.1\nFcalva 2025\n"); printf("fLisp interactive env - v0.1\nFcalva 2025\n");
printf("Under the terms of the GPL v3.0 license\n"); printf("Under the terms of the GPL v2.0 license\n");
yyin = stdin; yyin = stdin;
} }

View file

@ -35,9 +35,9 @@ ASTStack *stack;
void yyerror(char *s); void yyerror(char *s);
Tag ntag = {0,T_null}; Tag ntag = {0,0,T_null};
Tag atag = {0,T_any}; Tag atag = {0,0,T_any};
int make_stack(){ int make_stack(){
stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048); stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048);
@ -45,6 +45,8 @@ int make_stack(){
return 1; return 1;
if(heap_hashmap(&stack->symbol_map, SYMBOL_MAP_S)) if(heap_hashmap(&stack->symbol_map, SYMBOL_MAP_S))
return 1; return 1;
stack->funcs = NULL;
stack->fn_n = 0;
stack->stack_size = 2048; stack->stack_size = 2048;
symbol_map_add_bi(&stack->symbol_map); symbol_map_add_bi(&stack->symbol_map);
@ -52,10 +54,26 @@ int make_stack(){
} }
void free_stack(){ void free_stack(){
for(int i = 0; i < stack->curr_statement){
Statement *stat = &stack->statements[i];
if(stat->child_n)
free(stat->children);
}
free(stack->funcs);
free_hashmap(&stack->symbol_map); free_hashmap(&stack->symbol_map);
free(stack); free(stack);
} }
Statement *get_statement(){
if(stack->curr_statement >= stack->stack_size){
stack = realloc(stack, sizeof(ASTStack)+sizeof(Statement)*(stack->stack_size+2048));
if(!stack)
yyerror("Failed to extend stack");
stack->stack_size += 2048;
}
return &stack->statements[stack->curr_statement++];
}
char *bi_type_names[6] = { char *bi_type_names[6] = {
"", "",
"int", "int",
@ -68,22 +86,22 @@ char *bi_type_names[6] = {
Tag get_type(char *str){ Tag get_type(char *str){
for(int i = 1; i < 6; i++){ for(int i = 1; i < 6; i++){
if(!strcmp(bi_type_names[i], str)) if(!strcmp(bi_type_names[i], str))
return (Tag){0, i}; return (Tag){0,1,i};
} }
return (Tag){0, 0}; return (Tag){0,0,0};
} }
Statement *make_iconst(i32 val){ Statement *make_iconst(i32 val){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
stat->type = ST_Const; stat->type = ST_Const;
stat->cons = (Value){{.v4B = {val}},{.is_array = 0, .type = T_int}}; stat->cons = (Value){{.v4B = {.value=val}},{.is_array = 0, .type = T_int}};
stat->is_const = 1; stat->is_const = 1;
stat->child_n = 0; stat->child_n = 0;
return stat; return stat;
} }
Statement *make_fconst(float val){ Statement *make_fconst(float val){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
stat->type = ST_Const; stat->type = ST_Const;
stat->cons = (Value){{.v4B = {.vfl=val}},{.is_array=0,.type=T_float}}; stat->cons = (Value){{.v4B = {.vfl=val}},{.is_array=0,.type=T_float}};
stat->is_const = 1; stat->is_const = 1;
@ -92,8 +110,9 @@ Statement *make_fconst(float val){
} }
Statement *make_strconst(char *str){ Statement *make_strconst(char *str){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
stat->type = ST_Const; stat->type = ST_Const;
stat->is_const = 1;
i32 len = strcspn(str, "\""); i32 len = strcspn(str, "\"");
stat->cons = str_to_val(str, len); stat->cons = str_to_val(str, len);
return stat; return stat;
@ -105,7 +124,7 @@ Statement *declare(i32 type, Tag vtype, char *name, Statement *assign){
printf("declare : %d\n", vtype.type); printf("declare : %d\n", vtype.type);
#endif #endif
name[len] = '\0'; name[len] = '\0';
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
stat->type = type; stat->type = type;
if(hashmap_get(&stack->symbol_map, name)){ if(hashmap_get(&stack->symbol_map, name)){
yyerror("Redeclaring existing identifier"); yyerror("Redeclaring existing identifier");
@ -129,7 +148,7 @@ Statement *declare(i32 type, Tag vtype, char *name, Statement *assign){
} }
Statement *variable_get(char *name){ Statement *variable_get(char *name){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
MapItem *ret = hashmap_get(&stack->symbol_map, name); MapItem *ret = hashmap_get(&stack->symbol_map, name);
if(!ret) if(!ret)
yyerror("Undefined identifier"); yyerror("Undefined identifier");
@ -141,7 +160,7 @@ Statement *variable_get(char *name){
} }
Statement *make_block(Statement *first){ Statement *make_block(Statement *first){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
stat->type = ST_Block; stat->type = ST_Block;
stat->children = malloc(sizeof(void*)); stat->children = malloc(sizeof(void*));
stat->children[0] = first; stat->children[0] = first;
@ -160,11 +179,10 @@ Statement *add_block(Statement *block, Statement *add){
FnSig assign_sig = {.n_param = 1}; FnSig assign_sig = {.n_param = 1};
Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = get_statement();
if(nparam) if(nparam)
stat->children = malloc(sizeof(void*)*nparam); stat->children = malloc(sizeof(void*)*nparam);
stat->child_n = 0; stat->child_n = 0;
FnSig *fnsig = NULL;
va_list prm; va_list prm;
va_start(prm, nparam); va_start(prm, nparam);
@ -213,6 +231,53 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
return stat; return stat;
} }
void push_scope(){
if(stack->curr_scope >= 256)
yyerror("Scopes are too deep");
stack->scope_stack[stack->curr_scope++] = stack->scope_id++;
}
void pop_scope(){
if(stack->curr_scope <= 0)
yyerror("Weird scope error");
stack->curr_scope--;
}
char _mangle_tmp[36];
// 3 digit "Base64" scope id + { (invalid identifier char) + name
char *mangle_name(i32 scope, char *name){
// Scope 0 is global so we just return the name
if(!scope)
return name;
for(int i = 0; i < 3; i++){
_mangle_tmp[i] = (scope & 63) + ' ';
scope >>= 6;
}
_mangle_tmp[3] = '{';
strncpy(&_mangle_tmp[4], name, 32);
return _mangle_tmp;
}
FnArgs _fnargs;
FnArgs *make_fnargs(char *name, Tag type){
_fnargs.n_args = 1;
_fnargs.names[0] = name;
_fnargs.types[0] = type;
return &_fnargs;
}
FnArgs *add_fnargs(char *name, Tag type){
_fnargs.names[_fnargs.n_args] = name;
_fnargs.types[_fnargs.n_args++] = type;
return &_fnargs;
}
Statement *make_function(FnArgs *fn_args, Statement *statements){
Statement *stat = get_statement();
}
// TODO // TODO
void set_entry_point(Statement *statement){ void set_entry_point(Statement *statement){
printf("set_entry_point\n"); printf("set_entry_point\n");

View file

@ -23,6 +23,15 @@
#pragma once #pragma once
typedef struct {
// 0 is function name/output type
char *names[9];
Tag types[9];
i32 n_args;
} FnArgs;
void yyerror(char *s); void yyerror(char *s);
int make_stack(); int make_stack();
@ -32,9 +41,7 @@ void free_stack();
Tag get_type(char *str); Tag get_type(char *str);
Statement *make_iconst(i32 val); Statement *make_iconst(i32 val);
Statement *make_fconst(float val); Statement *make_fconst(float val);
//TODO
Statement *make_strconst(char *str); Statement *make_strconst(char *str);
Statement *declare(i32 type, Tag vtype, char *name, Statement *assign); Statement *declare(i32 type, Tag vtype, char *name, Statement *assign);
@ -42,9 +49,14 @@ Statement *declare(i32 type, Tag vtype, char *name, Statement *assign);
Statement *variable_get(char *name); Statement *variable_get(char *name);
Statement *make_block(Statement *first); Statement *make_block(Statement *first);
Statement *add_block(Statement *block, Statement *add); Statement *add_block(Statement *block, Statement *add);
Statement *make_operation(i32 type, Tag vtype, char *str, i32 nparam, ...); Statement *make_operation(i32 type, Tag vtype, char *str, i32 nparam, ...);
void push_scope();
void pop_scope();
FnArgs *make_fnargs(char *name, Tag type);
FnArgs *add_fnargs(char *name, Tag type);
void set_entry_point(Statement *statement); void set_entry_point(Statement *statement);

View file

@ -40,7 +40,10 @@
"if" return IF; "if" return IF;
"else" return ELSE; "else" return ELSE;
"while" return WHILE; "while" return WHILE;
"fn" return FN; "fn" {
push_scope();
return FN;
}
"var" return VAR; "var" return VAR;
"let" return LET; "let" return LET;
"block" return BLOCK; "block" return BLOCK;
@ -56,7 +59,7 @@
return G_IDENT; return G_IDENT;
} }
[0-9]+"."[0-9]+ { [0-9]*"."[0-9]+ {
yylval.st = make_fconst(atof(yytext)); yylval.st = make_fconst(atof(yytext));
return CST; return CST;
} }

View file

@ -37,6 +37,7 @@
char *str; char *str;
Statement *st; Statement *st;
Tag tag; Tag tag;
FnArgs *args;
} }
%nonassoc <str> G_IDENT %nonassoc <str> G_IDENT
@ -54,6 +55,7 @@
%type <st> expr expr_list %type <st> expr expr_list
%type <tag> type %type <tag> type
%type <args> fn_args
%% %%
@ -78,13 +80,13 @@ type:
fn_args: fn_args:
G_IDENT G_IDENT
{} {$$ = make_fnargs($1, atag);}
| G_IDENT type | G_IDENT type
{} {$$ = make_fnargs($1, $2);}
| fn_args G_IDENT | fn_args G_IDENT
{} {$$ = add_fnargs($2, atag);}
| fn_args G_IDENT type | fn_args G_IDENT type
{} {$$ = add_fnargs($2, $3);}
; ;
expr: expr:
@ -117,7 +119,9 @@ expr:
| '(' WHILE expr expr_list ')' | '(' WHILE expr expr_list ')'
{$$ = make_operation(BI_while, ntag, NULL, 2, $3, $4);} {$$ = make_operation(BI_while, ntag, NULL, 2, $3, $4);}
| '(' FN '(' fn_args ')' expr_list ')' | '(' FN '(' fn_args ')' expr_list ')'
{} {$$ = make_function($4, $6);
pop_scope();
}
| '(' BLOCK expr_list ')' | '(' BLOCK expr_list ')'
{$$ = $3;} {$$ = $3;}
| '(' G_IDENT expr_list ')' | '(' G_IDENT expr_list ')'

View file

@ -150,9 +150,23 @@ int t_make_fconst(){
return err; return err;
} }
// TODO
int t_make_strconst(){ int t_make_strconst(){
return 0; int err = 0;
Statement *st = NULL;
st = make_strconst("Hello world");
if(!st)
return 1;
err += st->type != ST_Const || !st->is_const || st->child_n;
err += st->cons.vstr.len != 11 || st->cons.tag.type != T_str;
err += strncmp(get_addr(st->cons.vstr.pos), "Hello world", 11);
st = make_strconst("Gatt");
if(!st)
return 1;
err += st->type != ST_Const || !st->is_const || st->child_n;
err += st->cons.vstr.len != 4 || st->cons.tag.type != T_str;
err += strncmp(st->cons.vstr.str, "Gatt", 4);
return err;
} }
int t_free_stack(){ int t_free_stack(){
@ -191,7 +205,7 @@ char *names[] = {
"make_stack", "make_stack",
"make_iconst", "make_iconst",
"make_fconst", "make_fconst",
"make_strconst (TODO)", "make_strconst",
"free_stack" "free_stack"
}; };