+ Builtins, strong types, - buffer overflow
This commit is contained in:
parent
b5f0ebc258
commit
dc208aed7c
4 changed files with 121 additions and 43 deletions
|
@ -77,7 +77,8 @@ 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;
|
||||||
|
|
||||||
|
|
|
@ -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,6 +253,11 @@ 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
|
#if LOG
|
||||||
|
@ -278,15 +281,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 +416,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){
|
||||||
|
@ -559,31 +561,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){
|
||||||
|
@ -633,21 +712,21 @@ 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))
|
||||||
|
|
||||||
|
@ -669,7 +748,7 @@ FnSig builtins[] = {
|
||||||
{{tvec,tany},2,1,{.bi = BICAST(push)}},
|
{{tvec,tany},2,1,{.bi = BICAST(push)}},
|
||||||
{{tvec,tint},2,1,{.bi = BICAST(pop)}},
|
{{tvec,tint},2,1,{.bi = BICAST(pop)}},
|
||||||
{{tany} ,1,1,{.bi = BICAST(fl_write)}},
|
{{tany} ,1,1,{.bi = BICAST(fl_write)}},
|
||||||
{{0} ,0,1,{.bi = BICAST(nwline)}}
|
{{tany} ,0,1,{.bi = BICAST(nwline)}}
|
||||||
};
|
};
|
||||||
|
|
||||||
char *bi_names[] = {
|
char *bi_names[] = {
|
||||||
|
@ -694,7 +773,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);
|
||||||
|
|
|
@ -37,18 +37,17 @@ 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 == src.tag.type || !dst->tag.is_strong) || 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:
|
||||||
|
@ -84,7 +83,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){
|
||||||
|
|
|
@ -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);
|
||||||
|
@ -68,15 +68,15 @@ 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 = &stack->statements[stack->curr_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;
|
||||||
|
@ -164,7 +164,6 @@ Statement *make_operation(i32 type, Tag vtype, char *name, i32 nparam, ...){
|
||||||
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue