This commit is contained in:
attilavs2 2025-03-12 22:25:34 +01:00
parent 07bd583b0d
commit 5a99cc1d06
12 changed files with 372 additions and 84 deletions

View file

@ -1,3 +1,6 @@
tmp:
- Finish varuse
- Load files - Load files
- Benchmarks - Benchmarks
- Tests - Tests

235
a.txt Normal file
View file

@ -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 ||<U+00A0>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

View file

@ -10,43 +10,42 @@ enum StatementTypes {
ST_None = 0, // Not processed yet ST_None = 0, // Not processed yet
ST_Call = 1, // Any kind of function call ST_Call = 1, // Any kind of function call
ST_Const = 2, // Constant ST_Const = 2, // Constant
ST_Var = 3, // Variable ST_Var = 3, // Free variable
ST_Block = 4, // Scope blocks ST_Block = 4, // Scope blocks
__stpass, ST_Varuse = 5, // Variable assign/potential func call
ST__end ST__end
}; };
// Special expressions and ones that map directly to bytecode // Special expressions and ones that map directly to bytecode
// Should mesh with StatementTypes // Should mesh with StatementTypes
enum BuiltinStatements { enum BuiltinStatements {
BI_assign = 6, BI_var = 6,
BI_var = 7, BI_let = 7,
BI_let = 8, BI_if = 8,
BI_if = 9, BI_else = 9,
BI_else = 10, BI_while = 10,
BI_while = 11, BI_fn = 11,
BI_fn = 12, BI_import = 12,
BI_import = 13, BI_is = 13,
BI_is = 14, BI_cast = 14,
BI_cast = 15, BI_add = 15,
BI_add = 16, BI_sub = 16,
BI_sub = 17, BI_mul = 17,
BI_mul = 18, BI_div = 18,
BI_div = 19, BI_mod = 19,
BI_mod = 20, BI_sml = 20,
BI_sml = 21, BI_sml_eq = 21,
BI_sml_eq = 22, BI_eq = 22,
BI_eq = 23, BI_gt_eq = 23,
BI_gt_eq = 24, BI_gt = 24,
BI_gt = 25, BI_not = 25,
BI_not = 26, BI_and = 26,
BI_and = 27, BI_or = 27,
BI_or = 28, BI_len = 28,
BI_len = 29, BI_push = 29,
BI_push = 30, BI_pop = 30,
BI_pop = 31, BI_write = 31,
BI_write = 32, BI_nwline = 32,
BI_nwline = 33,
BI__end BI__end
}; };
@ -89,4 +88,4 @@ typedef struct {
} ASTStack; } ASTStack;
_Static_assert((int)BI_assign >= ST__end); _Static_assert((int)BI_var >= ST__end);

View file

@ -4,3 +4,6 @@
// 1 : Some checks and prints // 1 : Some checks and prints
// 2 : All checks // 2 : All checks
#define DEBUG 2 #define DEBUG 2
// TODO : Automate this
#define INTERPR

View file

@ -5,6 +5,7 @@
#include "fixed.h" #include "fixed.h"
#include "types.h" #include "types.h"
#include "config.h"
#include "code_defs.h" #include "code_defs.h"
#include "byte_defs.h" #include "byte_defs.h"
#include "exec_common.h" #include "exec_common.h"
@ -52,12 +53,9 @@ int evaluate(Value val){
int alloc_init(){ int alloc_init(){
internal_buf = malloc(4096); internal_buf = malloc(4096);
printf("55\n");
blocks = malloc(sizeof(AllocBlock)); blocks = malloc(sizeof(AllocBlock));
printf("57\n");
block_count = 0; block_count = 0;
usage = malloc(sizeof(u32)*4096/32/8); usage = malloc(sizeof(u32)*4096/32/8);
printf("60\n");
if(!internal_buf || !blocks || !usage) if(!internal_buf || !blocks || !usage)
return 1; return 1;
memset(usage, 0, sizeof(u32)*4096/32/8); 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]); MapItem *ret = hashmap_insert(map, bi_names[i-BI_add]);
ret->type = *((i16*)&fntag); ret->type = *((i16*)&fntag);
ret->fnsig = &builtins[i-BI_add]; ret->fnsig = &builtins[i-BI_add];
ret->is_const = 1;
} }
} }

View file

@ -22,4 +22,6 @@ void *get_addr(u32 pos);
Value is(Tag tag, Value b); Value is(Tag tag, Value b);
Value cast(Tag tag, Value b);
void symbol_map_add_bi(HashMap *map); void symbol_map_add_bi(HashMap *map);

View file

@ -11,11 +11,12 @@
typedef struct { typedef struct {
i32 hash; // Hashs are internally 24bit for bytecode ops i32 hash;
char str[32]; char str[32];
i32 id; i32 id;
void *fnsig; void *fnsig;
i32 type; i32 type;
i32 is_const;
} MapItem; } MapItem;

View file

@ -3,16 +3,80 @@
#include <math.h> #include <math.h>
#include "fixed.h" #include "fixed.h"
#include "hash.h"
#include "types.h" #include "types.h"
#include "config.h"
#include "code_defs.h" #include "code_defs.h"
#include "byte_defs.h" #include "byte_defs.h"
#include "exec_common.h" #include "exec_common.h"
Value vars[SYMBOL_MAP_S]; 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 execute(Statement *stat){
Value returnv = {.tag = {0,T_null}}; Value returnv = {.tag = {0,T_null}};
switch(stat->type){ 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: case ST_None:
runtime_err("ST_None to process !"); runtime_err("ST_None to process !");
break; break;
@ -27,13 +91,13 @@ Value execute(Statement *stat){
returnv = execute(stat->children[i]); returnv = execute(stat->children[i]);
} }
break; break;
case BI_assign:
vars[stat->var_id] = execute(stat->children[0]);
break;
case BI_var: case BI_var:
case BI_let: 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; vars[stat->var_id].tag = stat->var_type;
if(stat->child_n)
assign(&vars[stat->var_id],execute(stat->children[0]));
break; break;
case BI_if: case BI_if:
if(evaluate(execute(stat->children[0]))) if(evaluate(execute(stat->children[0])))
@ -54,31 +118,15 @@ Value execute(Statement *stat){
case BI_is: case BI_is:
returnv = is(stat->var_type, execute(stat->children[0])); returnv = is(stat->var_type, execute(stat->children[0]));
break; break;
// TODO
case BI_cast: case BI_cast:
returnv = cast(stat->var_type, execute(stat->children[0]));
break; break;
case ST_Call: case ST_Call:
FnSig *fn = stat->func; FnSig *fn = stat->func;
Statement **params; Statement **params = NULL;
if(fn->n_param) if(fn->n_param)
params = (Statement**)((Statement*)stat->children[0])->children; params = (Statement**)((Statement*)stat->children[0])->children;
if(fn->is_builtin){ returnv = fncall(fn, params);
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;
}
}
break; break;
} }
return returnv; return returnv;

View file

@ -17,6 +17,8 @@ void yyerror(char *s);
Tag ntag = {0,T_null}; Tag ntag = {0,T_null};
Tag atag = {0,T_any};
int make_stack(){ int make_stack(){
stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048); stack = malloc(sizeof(ASTStack)+sizeof(Statement)*2048);
if(!stack) 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)"); i32 len = strcspn(name, " \t\n)");
printf("declare : %d\n", vtype.type);
char *name2 = strndup(name, len); char *name2 = strndup(name, len);
Statement *stat = &stack->statements[stack->curr_statement++]; Statement *stat = &stack->statements[stack->curr_statement++];
stat->type = type; stat->type = type;
@ -70,6 +73,12 @@ Statement *declare(i32 type, Tag vtype, char *name){
ret->type = *((i16*)&vtype); ret->type = *((i16*)&vtype);
stat->var_id = ret->id; stat->var_id = ret->id;
stat->var_type = vtype; stat->var_type = vtype;
if(assign){
stat->child_n = 1;
stat->children = malloc(sizeof(void*));
stat->children[0] = assign;
}
else
stat->child_n = 0; stat->child_n = 0;
return stat; return stat;
@ -106,10 +115,6 @@ Statement *add_block(Statement *block, Statement *add){
FnSig assign_sig = {.n_param = 1}; FnSig assign_sig = {.n_param = 1};
FnSig bi_sig[] = {
};
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 = &stack->statements[stack->curr_statement++];
if(nparam) if(nparam)
@ -124,27 +129,18 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
if(!type || type == ST_Call){ if(!type || type == ST_Call){
i32 len = strcspn(name, " \t\n()"); i32 len = strcspn(name, " \t\n()");
char *name2 = strndup(name, len); char *name2 = strndup(name, len);
printf("name : \"%s\" ; name2 : \"%s\"\n",name,name2);
MapItem *ret = hashmap_get(&stack->symbol_map, name2); MapItem *ret = hashmap_get(&stack->symbol_map, name2);
free(name2); free(name2);
if(!ret) if(!ret)
yyerror("Undefined identifer"); yyerror("Undefined identifer");
if(nparam > 1 && ret->type != T_fn) if(ret->is_const && ret->type == T_fn){
yyerror("Too many parameters to assignement"); type = ST_Call;
if(((Tag*)&ret->type)->type != T_fn){ stat->func = ret->fnsig;
type = BI_assign;
assign_sig.params[0] = *((Tag*)&ret->type);
fnsig = &assign_sig;
} }
else { else {
fnsig = ret->fnsig; type = ST_Varuse;
type = ST_Call; stat->var_id = ret->id;
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");
} }
} }
if(type == BI_is || type == BI_cast) if(type == BI_is || type == BI_cast)

View file

@ -16,7 +16,7 @@ Statement *make_iconst(i32 val);
Statement *make_fconst(float val); Statement *make_fconst(float val);
Statement *make_strconst(char *str); 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); 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); void set_entry_point(Statement *statement);
extern Tag ntag; extern Tag ntag;
extern Tag atag;

View file

@ -65,13 +65,13 @@ expr:
'(' G_IDENT ')' '(' G_IDENT ')'
{$$ = make_operation(ST_Call,ntag,$2,0);} {$$ = make_operation(ST_Call,ntag,$2,0);}
| '(' VAR G_IDENT ')' | '(' VAR G_IDENT ')'
{ $$ = declare(BI_var,ntag,$3);} { $$ = declare(BI_var,atag,$3,NULL);}
| '(' VAR type G_IDENT ')' | '(' VAR type G_IDENT ')'
{$$ = declare(BI_var, $3, $4);} {$$ = declare(BI_var, $3, $4, NULL);}
| '(' VAR G_IDENT expr')' | '(' VAR G_IDENT expr')'
{$$ = declare(BI_var,ntag,$3);} {$$ = declare(BI_var,atag,$3,$4);}
| '(' VAR type G_IDENT expr ')' | '(' VAR type G_IDENT expr ')'
{$$ = declare(BI_var,$3,$4);} {$$ = declare(BI_var,$3,$4,$5);}
| '(' LET G_IDENT ')' | '(' LET G_IDENT ')'
{} {}
| '(' LET type G_IDENT ')' | '(' LET type G_IDENT ')'

View file

@ -28,5 +28,6 @@ enum ValTypes {
T_float = 3, T_float = 3,
T_str = 4, T_str = 4,
T_fn = 5, T_fn = 5,
T_any = 6
}; };