From 5a99cc1d06530a70454a4637fe372f5c9430e2e5 Mon Sep 17 00:00:00 2001 From: attilavs2 Date: Wed, 12 Mar 2025 22:25:34 +0100 Subject: [PATCH] WIP --- TODO.md | 3 + a.txt | 235 ++++++++++++++++++++++++++++++++++++++++++++++ src/code_defs.h | 61 ++++++------ src/config.h | 3 + src/exec_common.c | 5 +- src/exec_common.h | 2 + src/hash.h | 3 +- src/interpreter.c | 94 ++++++++++++++----- src/parse_utils.c | 38 ++++---- src/parser.h | 3 +- src/parser.y | 8 +- src/types.h | 1 + 12 files changed, 372 insertions(+), 84 deletions(-) create mode 100644 a.txt diff --git a/TODO.md b/TODO.md index 07089b0..f0227bb 100644 --- a/TODO.md +++ b/TODO.md @@ -1,3 +1,6 @@ +tmp: + - Finish varuse + - Load files - Benchmarks - Tests diff --git a/a.txt b/a.txt new file mode 100644 index 0000000..d4a68f9 --- /dev/null +++ b/a.txt @@ -0,0 +1,235 @@ +mkdir: cannot create directory ‘build’: File exists +make: [Makefile:33: builddir] Error 1 (ignored) +mkdir: cannot create directory ‘build-tmp’: File exists +make: [Makefile:34: builddir] Error 1 (ignored) +mv: missing destination file operand after 'build-tmp/' +Try 'mv --help' for more information. +make: [Makefile:36: builddir] Error 1 (ignored) +parser.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] +parser.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples +lex.yy.c:1248:16: warning: ‘input’ defined but not used [-Wunused-function] +lex.yy.c:1205:17: warning: ‘yyunput’ defined but not used [-Wunused-function] +src/exec_common.c: In function ‘assign’: +src/exec_common.c:55:39: error: stray ‘\302’ in program + 55 | if((dst->tag.type == src.tag.type ||dst->tag.type == T_any) + | ^~~~~~~~ +src/exec_common.c: In function ‘fncall’: +src/exec_common.c:69:9: error: ‘returnv’ undeclared (first use in this function) + 69 | returnv = fn->bi(); + | ^~~~~~~ +src/exec_common.c:69:9: note: each undeclared identifier is reported only once for each function it appears in +src/exec_common.c:73:23: warning: implicit declaration of function ‘execute’ [-Wimplicit-function-declaration] + 73 | returnv = fn1(execute(params[0])); + | ^~~~~~~ +src/exec_common.c:73:23: error: incompatible type for argument 1 of ‘fn1’ + 73 | returnv = fn1(execute(params[0])); + | ^~~~~~~~~~~~~~~~~~ + | | + | int +src/exec_common.c:73:23: note: expected ‘Value’ but argument is of type ‘int’ +src/exec_common.c:77:23: error: incompatible type for argument 1 of ‘fn2’ + 77 | returnv = fn2(execute(params[0]),execute(params[1])); + | ^~~~~~~~~~~~~~~~~~ + | | + | int +src/exec_common.c:77:23: note: expected ‘Value’ but argument is of type ‘int’ +src/exec_common.c:77:42: error: incompatible type for argument 2 of ‘fn2’ + 77 | returnv = fn2(execute(params[0]),execute(params[1])); + | ^~~~~~~~~~~~~~~~~~ + | | + | int +src/exec_common.c:77:42: note: expected ‘Value’ but argument is of type ‘int’ +src/exec_common.c:85:12: error: incompatible types when returning type ‘int’ but ‘Value’ was expected + 85 | return execute(fn->stmt); + | ^~~~~~~~~~~~~~~~~ +src/exec_common.c: In function ‘flisp_free’: +src/exec_common.c:136:21: warning: unused parameter ‘pos’ [-Wunused-parameter] + 136 | void flisp_free(u32 pos){ + | ~~~~^~~ +src/exec_common.c: In function ‘int_to_str’: +src/exec_common.c:190:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 190 | Value int_to_str(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘fix_to_str’: +src/exec_common.c:194:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 194 | Value fix_to_str(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘flt_to_str’: +src/exec_common.c:198:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 198 | Value flt_to_str(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘str_to_int’: +src/exec_common.c:202:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 202 | Value str_to_int(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘str_to_fix’: +src/exec_common.c:206:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 206 | Value str_to_fix(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘str_to_flt’: +src/exec_common.c:210:24: warning: unused parameter ‘x’ [-Wunused-parameter] + 210 | Value str_to_flt(Value x){ + | ~~~~~~^ +src/exec_common.c: In function ‘sml’: +src/exec_common.c:346:17: warning: unused parameter ‘a’ [-Wunused-parameter] + 346 | Value sml(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:346:26: warning: unused parameter ‘b’ [-Wunused-parameter] + 346 | Value sml(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘sml_eq’: +src/exec_common.c:350:20: warning: unused parameter ‘a’ [-Wunused-parameter] + 350 | Value sml_eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:350:29: warning: unused parameter ‘b’ [-Wunused-parameter] + 350 | Value sml_eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘eq’: +src/exec_common.c:354:16: warning: unused parameter ‘a’ [-Wunused-parameter] + 354 | Value eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:354:25: warning: unused parameter ‘b’ [-Wunused-parameter] + 354 | Value eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘gt_eq’: +src/exec_common.c:358:19: warning: unused parameter ‘a’ [-Wunused-parameter] + 358 | Value gt_eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:358:28: warning: unused parameter ‘b’ [-Wunused-parameter] + 358 | Value gt_eq(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘gt’: +src/exec_common.c:362:16: warning: unused parameter ‘a’ [-Wunused-parameter] + 362 | Value gt(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:362:25: warning: unused parameter ‘b’ [-Wunused-parameter] + 362 | Value gt(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘not’: +src/exec_common.c:366:17: warning: unused parameter ‘a’ [-Wunused-parameter] + 366 | Value not(Value a){ + | ~~~~~~^ +src/exec_common.c: In function ‘and’: +src/exec_common.c:370:17: warning: unused parameter ‘a’ [-Wunused-parameter] + 370 | Value and(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:370:26: warning: unused parameter ‘b’ [-Wunused-parameter] + 370 | Value and(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘or’: +src/exec_common.c:374:16: warning: unused parameter ‘a’ [-Wunused-parameter] + 374 | Value or(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:374:25: warning: unused parameter ‘b’ [-Wunused-parameter] + 374 | Value or(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘len’: +src/exec_common.c:378:17: warning: unused parameter ‘a’ [-Wunused-parameter] + 378 | Value len(Value a){ + | ~~~~~~^ +src/exec_common.c: In function ‘push’: +src/exec_common.c:382:18: warning: unused parameter ‘a’ [-Wunused-parameter] + 382 | Value push(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:382:27: warning: unused parameter ‘b’ [-Wunused-parameter] + 382 | Value push(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: In function ‘pop’: +src/exec_common.c:386:17: warning: unused parameter ‘a’ [-Wunused-parameter] + 386 | Value pop(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c:386:26: warning: unused parameter ‘b’ [-Wunused-parameter] + 386 | Value pop(Value a, Value b){ + | ~~~~~~^ +src/exec_common.c: At top level: +src/exec_common.c:441:20: warning: missing braces around initializer [-Wmissing-braces] + 441 | FnSig builtins[] = { + | ^ +...... + 459 | {{0} ,0,1,{.bi = BICAST(nwline)}} + | {} +src/exec_common.c:441:20: warning: missing braces around initializer [-Wmissing-braces] + 441 | FnSig builtins[] = { + | ^ +...... + 459 | {{0} ,0,1,{.bi = BICAST(nwline)}} + | {} +src/exec_common.c:441:20: warning: missing braces around initializer [-Wmissing-braces] + 441 | FnSig builtins[] = { + | ^ +...... + 459 | {{0} ,0,1,{.bi = BICAST(nwline)}} + | {} +src/exec_common.c: In function ‘fncall’: +src/exec_common.c:90:1: warning: control reaches end of non-void function [-Wreturn-type] + 90 | } + | ^ +src/exec_common.c: In function ‘int_to_str’: +src/exec_common.c:192:1: warning: control reaches end of non-void function [-Wreturn-type] + 192 | } + | ^ +src/exec_common.c: In function ‘fix_to_str’: +src/exec_common.c:196:1: warning: control reaches end of non-void function [-Wreturn-type] + 196 | } + | ^ +src/exec_common.c: In function ‘flt_to_str’: +src/exec_common.c:200:1: warning: control reaches end of non-void function [-Wreturn-type] + 200 | } + | ^ +src/exec_common.c: In function ‘str_to_int’: +src/exec_common.c:204:1: warning: control reaches end of non-void function [-Wreturn-type] + 204 | } + | ^ +src/exec_common.c: In function ‘str_to_fix’: +src/exec_common.c:208:1: warning: control reaches end of non-void function [-Wreturn-type] + 208 | } + | ^ +src/exec_common.c: In function ‘str_to_flt’: +src/exec_common.c:212:1: warning: control reaches end of non-void function [-Wreturn-type] + 212 | } + | ^ +src/exec_common.c: In function ‘sml’: +src/exec_common.c:348:1: warning: control reaches end of non-void function [-Wreturn-type] + 348 | } + | ^ +src/exec_common.c: In function ‘sml_eq’: +src/exec_common.c:352:1: warning: control reaches end of non-void function [-Wreturn-type] + 352 | } + | ^ +src/exec_common.c: In function ‘eq’: +src/exec_common.c:356:1: warning: control reaches end of non-void function [-Wreturn-type] + 356 | } + | ^ +src/exec_common.c: In function ‘gt_eq’: +src/exec_common.c:360:1: warning: control reaches end of non-void function [-Wreturn-type] + 360 | } + | ^ +src/exec_common.c: In function ‘gt’: +src/exec_common.c:364:1: warning: control reaches end of non-void function [-Wreturn-type] + 364 | } + | ^ +src/exec_common.c: In function ‘not’: +src/exec_common.c:368:1: warning: control reaches end of non-void function [-Wreturn-type] + 368 | } + | ^ +src/exec_common.c: In function ‘and’: +src/exec_common.c:372:1: warning: control reaches end of non-void function [-Wreturn-type] + 372 | } + | ^ +src/exec_common.c: In function ‘or’: +src/exec_common.c:376:1: warning: control reaches end of non-void function [-Wreturn-type] + 376 | } + | ^ +src/exec_common.c: In function ‘len’: +src/exec_common.c:380:1: warning: control reaches end of non-void function [-Wreturn-type] + 380 | } + | ^ +src/exec_common.c: In function ‘push’: +src/exec_common.c:384:1: warning: control reaches end of non-void function [-Wreturn-type] + 384 | } + | ^ +src/exec_common.c: In function ‘pop’: +src/exec_common.c:388:1: warning: control reaches end of non-void function [-Wreturn-type] + 388 | } + | ^ +make: *** [Makefile:44: build-tmp/exec_common.o] Error 1 diff --git a/src/code_defs.h b/src/code_defs.h index 1838d8c..e74e1e3 100755 --- a/src/code_defs.h +++ b/src/code_defs.h @@ -10,43 +10,42 @@ enum StatementTypes { ST_None = 0, // Not processed yet ST_Call = 1, // Any kind of function call ST_Const = 2, // Constant - ST_Var = 3, // Variable + ST_Var = 3, // Free variable ST_Block = 4, // Scope blocks - __stpass, + ST_Varuse = 5, // Variable assign/potential func call ST__end }; // Special expressions and ones that map directly to bytecode // Should mesh with StatementTypes enum BuiltinStatements { - BI_assign = 6, - BI_var = 7, - BI_let = 8, - BI_if = 9, - BI_else = 10, - BI_while = 11, - BI_fn = 12, - BI_import = 13, - BI_is = 14, - BI_cast = 15, - BI_add = 16, - BI_sub = 17, - BI_mul = 18, - BI_div = 19, - BI_mod = 20, - BI_sml = 21, - BI_sml_eq = 22, - BI_eq = 23, - BI_gt_eq = 24, - BI_gt = 25, - BI_not = 26, - BI_and = 27, - BI_or = 28, - BI_len = 29, - BI_push = 30, - BI_pop = 31, - BI_write = 32, - BI_nwline = 33, + BI_var = 6, + BI_let = 7, + BI_if = 8, + BI_else = 9, + BI_while = 10, + BI_fn = 11, + BI_import = 12, + BI_is = 13, + BI_cast = 14, + BI_add = 15, + BI_sub = 16, + BI_mul = 17, + BI_div = 18, + BI_mod = 19, + BI_sml = 20, + BI_sml_eq = 21, + BI_eq = 22, + BI_gt_eq = 23, + BI_gt = 24, + BI_not = 25, + BI_and = 26, + BI_or = 27, + BI_len = 28, + BI_push = 29, + BI_pop = 30, + BI_write = 31, + BI_nwline = 32, BI__end }; @@ -89,4 +88,4 @@ typedef struct { } ASTStack; -_Static_assert((int)BI_assign >= ST__end); +_Static_assert((int)BI_var >= ST__end); diff --git a/src/config.h b/src/config.h index ae86007..d7cd04e 100755 --- a/src/config.h +++ b/src/config.h @@ -4,3 +4,6 @@ // 1 : Some checks and prints // 2 : All checks #define DEBUG 2 + +// TODO : Automate this +#define INTERPR diff --git a/src/exec_common.c b/src/exec_common.c index d208f10..ba87341 100644 --- a/src/exec_common.c +++ b/src/exec_common.c @@ -5,6 +5,7 @@ #include "fixed.h" #include "types.h" +#include "config.h" #include "code_defs.h" #include "byte_defs.h" #include "exec_common.h" @@ -52,12 +53,9 @@ int evaluate(Value val){ int alloc_init(){ internal_buf = malloc(4096); - printf("55\n"); blocks = malloc(sizeof(AllocBlock)); - printf("57\n"); block_count = 0; usage = malloc(sizeof(u32)*4096/32/8); - printf("60\n"); if(!internal_buf || !blocks || !usage) return 1; memset(usage, 0, sizeof(u32)*4096/32/8); @@ -450,5 +448,6 @@ void symbol_map_add_bi(HashMap *map){ MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]); ret->type = *((i16*)&fntag); ret->fnsig = &builtins[i-BI_add]; + ret->is_const = 1; } } diff --git a/src/exec_common.h b/src/exec_common.h index 0f8a9c0..602cdab 100644 --- a/src/exec_common.h +++ b/src/exec_common.h @@ -22,4 +22,6 @@ void *get_addr(u32 pos); Value is(Tag tag, Value b); +Value cast(Tag tag, Value b); + void symbol_map_add_bi(HashMap *map); diff --git a/src/hash.h b/src/hash.h index b26c0bf..f89ec45 100755 --- a/src/hash.h +++ b/src/hash.h @@ -11,11 +11,12 @@ typedef struct { - i32 hash; // Hashs are internally 24bit for bytecode ops + i32 hash; char str[32]; i32 id; void *fnsig; i32 type; + i32 is_const; } MapItem; diff --git a/src/interpreter.c b/src/interpreter.c index 63b89fa..33336c5 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -3,16 +3,80 @@ #include #include "fixed.h" +#include "hash.h" #include "types.h" +#include "config.h" #include "code_defs.h" #include "byte_defs.h" #include "exec_common.h" Value vars[SYMBOL_MAP_S]; +Value execute(Statement *stat); + +void assign(Value *dst, Value src){ + printf("Assign : %d -> %d\n", src.tag.type, dst->tag.type); + if((dst->tag.type == src.tag.type || dst->tag.type == T_any) + && dst->tag.is_array == src.tag.is_array) + *dst = src; + else{ + fprintf(stderr, "Warning : Possibly incorrect assignement\n" + "This may error in the future\n"); + *dst = src; + } +} + +Value fncall(FnSig *fn, Statement **params){ + Value returnv = {.tag = {0, T_null}}; + if(fn->is_builtin){ + switch(fn->n_param){ + case 0: + returnv = fn->bi(); + break; + case 1: + Value (*fn1)(Value) = (void*)fn->bi; + returnv = fn1(execute(params[0])); + break; + case 2: + Value (*fn2)(Value,Value) = (void*)fn->bi; + returnv = fn2(execute(params[0]),execute(params[1])); + break; + default: + runtime_err("Call to builtin with >2 params"); + break; + } + } + else { +#ifdef INTERPR + returnv = execute(fn->stmt); +#else + #warning "fncall not implemented for compiler" +#endif + } + return returnv; +} + +void init_exec(){ + +} + Value execute(Statement *stat){ Value returnv = {.tag = {0,T_null}}; switch(stat->type){ + case ST_Varuse: + if(vars[stat->var_id].tag.type == T_fn){ + Statement **params = NULL; + FnSig *fn = get_fnsig(&vars[stat->var_id]); + if(fn->n_param) + params = (Statement**)((Statement*)stat->children[0])->children; + fncall(fn, params); + } + else { + printf("stvar : %d\n", vars[stat->var_id].tag.type); + assign(&vars[stat->var_id], execute(stat->children[0])); + } + + break; case ST_None: runtime_err("ST_None to process !"); break; @@ -27,13 +91,13 @@ Value execute(Statement *stat){ returnv = execute(stat->children[i]); } break; - case BI_assign: - vars[stat->var_id] = execute(stat->children[0]); - break; case BI_var: case BI_let: - // Init the relevant value for correct "is" + // Init the relevant value for correct type checks + printf("var : %d\n", stat->var_type.type); vars[stat->var_id].tag = stat->var_type; + if(stat->child_n) + assign(&vars[stat->var_id],execute(stat->children[0])); break; case BI_if: if(evaluate(execute(stat->children[0]))) @@ -54,31 +118,15 @@ Value execute(Statement *stat){ case BI_is: returnv = is(stat->var_type, execute(stat->children[0])); break; - // TODO case BI_cast: + returnv = cast(stat->var_type, execute(stat->children[0])); break; case ST_Call: FnSig *fn = stat->func; - Statement **params; + Statement **params = NULL; if(fn->n_param) params = (Statement**)((Statement*)stat->children[0])->children; - if(fn->is_builtin){ - switch(fn->n_param){ - case 0: - returnv = fn->bi(); - break; - case 1: - Value (*fn1)(Value) = (void*)fn->bi; - returnv = fn1(execute(params[0])); - break; - case 2: - Value (*fn2)(Value,Value) = (void*)fn->bi; - returnv = fn2(execute(params[0]),execute(params[1])); - break; - default: - break; - } - } + returnv = fncall(fn, params); break; } return returnv; diff --git a/src/parse_utils.c b/src/parse_utils.c index 9e4e7e3..81fe5e2 100644 --- a/src/parse_utils.c +++ b/src/parse_utils.c @@ -17,6 +17,8 @@ void yyerror(char *s); Tag ntag = {0,T_null}; +Tag atag = {0,T_any}; + int make_stack(){ stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048); if(!stack) @@ -58,8 +60,9 @@ Statement *make_strconst(char *str){ } -Statement *declare(i32 type, Tag vtype, char *name){ +Statement *declare(i32 type, Tag vtype, char *name, Statement *assign){ i32 len = strcspn(name, " \t\n)"); + printf("declare : %d\n", vtype.type); char *name2 = strndup(name, len); Statement *stat = &stack->statements[stack->curr_statement++]; stat->type = type; @@ -70,7 +73,13 @@ Statement *declare(i32 type, Tag vtype, char *name){ ret->type = *((i16*)&vtype); stat->var_id = ret->id; stat->var_type = vtype; - stat->child_n = 0; + if(assign){ + stat->child_n = 1; + stat->children = malloc(sizeof(void*)); + stat->children[0] = assign; + } + else + stat->child_n = 0; return stat; } @@ -106,10 +115,6 @@ Statement *add_block(Statement *block, Statement *add){ FnSig assign_sig = {.n_param = 1}; -FnSig bi_sig[] = { - -}; - Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){ Statement *stat = &stack->statements[stack->curr_statement++]; if(nparam) @@ -124,27 +129,18 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){ if(!type || type == ST_Call){ i32 len = strcspn(name, " \t\n()"); char *name2 = strndup(name, len); + printf("name : \"%s\" ; name2 : \"%s\"\n",name,name2); MapItem *ret = hashmap_get(&stack->symbol_map, name2); free(name2); if(!ret) yyerror("Undefined identifer"); - if(nparam > 1 && ret->type != T_fn) - yyerror("Too many parameters to assignement"); - if(((Tag*)&ret->type)->type != T_fn){ - type = BI_assign; - assign_sig.params[0] = *((Tag*)&ret->type); - fnsig = &assign_sig; + if(ret->is_const && ret->type == T_fn){ + type = ST_Call; + stat->func = ret->fnsig; } else { - fnsig = ret->fnsig; - type = ST_Call; - stat->func = fnsig; - } - if(nparam){ - if(!fnsig) - yyerror("Calling function that has not been specified"); - if(param->child_n > fnsig->n_param) - yyerror("Too many parameters to function"); + type = ST_Varuse; + stat->var_id = ret->id; } } if(type == BI_is || type == BI_cast) diff --git a/src/parser.h b/src/parser.h index 88382de..4e252f2 100644 --- a/src/parser.h +++ b/src/parser.h @@ -16,7 +16,7 @@ Statement *make_iconst(i32 val); Statement *make_fconst(float val); Statement *make_strconst(char *str); -Statement *declare(i32 type, Tag vtype, char *name); +Statement *declare(i32 type, Tag vtype, char *name, Statement *assign); Statement *variable_get(char *name); @@ -29,3 +29,4 @@ Statement *make_operation(i32 type, Tag vtype, char *str, i32 nparam, ...); void set_entry_point(Statement *statement); extern Tag ntag; +extern Tag atag; diff --git a/src/parser.y b/src/parser.y index a2ad6ef..1e1554e 100644 --- a/src/parser.y +++ b/src/parser.y @@ -65,13 +65,13 @@ expr: '(' G_IDENT ')' {$$ = make_operation(ST_Call,ntag,$2,0);} | '(' VAR G_IDENT ')' - { $$ = declare(BI_var,ntag,$3);} + { $$ = declare(BI_var,atag,$3,NULL);} | '(' VAR type G_IDENT ')' - {$$ = declare(BI_var, $3, $4);} + {$$ = declare(BI_var, $3, $4, NULL);} | '(' VAR G_IDENT expr')' - {$$ = declare(BI_var,ntag,$3);} + {$$ = declare(BI_var,atag,$3,$4);} | '(' VAR type G_IDENT expr ')' - {$$ = declare(BI_var,$3,$4);} + {$$ = declare(BI_var,$3,$4,$5);} | '(' LET G_IDENT ')' {} | '(' LET type G_IDENT ')' diff --git a/src/types.h b/src/types.h index b68655a..87f77b4 100755 --- a/src/types.h +++ b/src/types.h @@ -28,5 +28,6 @@ enum ValTypes { T_float = 3, T_str = 4, T_fn = 5, + T_any = 6 };