fix memory leak + add function to convert to string
This commit is contained in:
parent
4d5cd93354
commit
6f91a71306
55
main.c
55
main.c
@ -127,6 +127,40 @@ static Value fn_ptr(Value *args) {
|
|||||||
return (Value){ .type = TypePtr, .Ptr = { .type = TypeVoid, .val = NULL }};
|
return (Value){ .type = TypePtr, .Ptr = { .type = TypeVoid, .val = NULL }};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Value fn_string(Value *args) {
|
||||||
|
char *res = xmalloc(64);
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
switch (args[0].type) {
|
||||||
|
case TypeVoid: strcpy(res, "(void)"); len = 6; break;
|
||||||
|
case TypeFloat: len = snprintf(res, 64, "%f", args[0].Float); break;
|
||||||
|
case TypeInt: len = snprintf(res, 64, "%zd", args[0].Int); break;
|
||||||
|
case TypeBool:
|
||||||
|
if (args[0].Bool) {
|
||||||
|
strcpy(res, "true");
|
||||||
|
len = 4;
|
||||||
|
} else {
|
||||||
|
strcpy(res, "false");
|
||||||
|
len = 5;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TypeChar: res[0] = args[0].Char; len = 1; break;
|
||||||
|
default: ASSERT_UNREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Value){
|
||||||
|
.type = TypeArr,
|
||||||
|
.Arr = {
|
||||||
|
.is_string = true,
|
||||||
|
.dynamically_allocated = true,
|
||||||
|
.type = TypeChar,
|
||||||
|
.vals = res,
|
||||||
|
.len = len,
|
||||||
|
.cap = 64,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static Value fn_pow(Value *args) {
|
static Value fn_pow(Value *args) {
|
||||||
if (!(args[0].type == TypeFloat && args[1].type == TypeFloat)) {
|
if (!(args[0].type == TypeFloat && args[1].type == TypeFloat)) {
|
||||||
set_err("pow() requires arguments of type float");
|
set_err("pow() requires arguments of type float");
|
||||||
@ -232,16 +266,17 @@ int main(int argc, const char **argv) {
|
|||||||
print_toks(&tokens);
|
print_toks(&tokens);
|
||||||
/* parse tokens into IR code */
|
/* parse tokens into IR code */
|
||||||
BuiltinFunc funcs[] = {
|
BuiltinFunc funcs[] = {
|
||||||
{ .name = "put", .kind = FuncVarArgs, .returns = false, .side_effects = true, .VarArgs = { .min_args = 0, .NoRet.func = fn_put, }},
|
{ .name = "put", .kind = FuncVarArgs, .returns = false, .side_effects = true, .VarArgs = { .min_args = 0, .NoRet.func = fn_put, }},
|
||||||
{ .name = "putln", .kind = FuncVarArgs, .returns = false, .side_effects = true, .VarArgs = { .min_args = 0, .NoRet.func = fn_putln, }},
|
{ .name = "putln", .kind = FuncVarArgs, .returns = false, .side_effects = true, .VarArgs = { .min_args = 0, .NoRet.func = fn_putln, }},
|
||||||
{ .name = "int", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_int, }},
|
{ .name = "int", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_int, }},
|
||||||
{ .name = "float", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_float, }},
|
{ .name = "float", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_float, }},
|
||||||
{ .name = "bool", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_bool, }},
|
{ .name = "bool", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_bool, }},
|
||||||
{ .name = "char", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_char, }},
|
{ .name = "char", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_char, }},
|
||||||
{ .name = "ptr", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 0, .WithRet.func = fn_ptr, }},
|
{ .name = "ptr", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 0, .WithRet.func = fn_ptr, }},
|
||||||
{ .name = "pow", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 2, .WithRet.func = fn_pow, }},
|
{ .name = "string", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 1, .WithRet.func = fn_string, }},
|
||||||
{ .name = "sleep", .kind = FuncFixedArgs, .returns = false, .side_effects = true, .FixedArgs = { .n_args = 1, .NoRet.func = fn_sleep, }},
|
{ .name = "pow", .kind = FuncFixedArgs, .returns = true, .side_effects = false, .FixedArgs = { .n_args = 2, .WithRet.func = fn_pow, }},
|
||||||
{ .name = "getln", .kind = FuncFixedArgs, .returns = true, .side_effects = true, .FixedArgs = { .n_args = 0, .WithRet.func = fn_getln, }},
|
{ .name = "sleep", .kind = FuncFixedArgs, .returns = false, .side_effects = true, .FixedArgs = { .n_args = 1, .NoRet.func = fn_sleep, }},
|
||||||
|
{ .name = "getln", .kind = FuncFixedArgs, .returns = true, .side_effects = true, .FixedArgs = { .n_args = 0, .WithRet.func = fn_getln, }},
|
||||||
};
|
};
|
||||||
IRList ir = parse(&tokens, funcs, sizeof(funcs) / sizeof(funcs[0]));
|
IRList ir = parse(&tokens, funcs, sizeof(funcs) / sizeof(funcs[0]));
|
||||||
if (err) {
|
if (err) {
|
||||||
|
14
parse.c
14
parse.c
@ -31,6 +31,7 @@ static IRParam tok_to_irparam(Scope *sc, Tok *t);
|
|||||||
static Scope make_scope(Scope *parent, bool with_idents);
|
static Scope make_scope(Scope *parent, bool with_idents);
|
||||||
static void term_scope(Scope *sc);
|
static void term_scope(Scope *sc);
|
||||||
static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret);
|
static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret);
|
||||||
|
static void make_value_statically_allocated(Value *v);
|
||||||
static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
|
static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
|
||||||
static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr);
|
static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr);
|
||||||
static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
|
static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t);
|
||||||
@ -160,6 +161,13 @@ static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void make_value_statically_allocated(Value *v) {
|
||||||
|
switch (v->type) {
|
||||||
|
case TypeArr: v->Arr.dynamically_allocated = false; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The job of this function is to reduce the expression to the most simple form
|
/* The job of this function is to reduce the expression to the most simple form
|
||||||
* writing the least IR instructions possible (without overanalyzing).
|
* writing the least IR instructions possible (without overanalyzing).
|
||||||
* This means that the only IR instructions it will be writing are those for
|
* This means that the only IR instructions it will be writing are those for
|
||||||
@ -355,6 +363,12 @@ static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
|
|||||||
func.VarArgs.WithRet.func(args_len - func.VarArgs.min_args, arg_vals)
|
func.VarArgs.WithRet.func(args_len - func.VarArgs.min_args, arg_vals)
|
||||||
: func.FixedArgs.WithRet.func(arg_vals),
|
: func.FixedArgs.WithRet.func(arg_vals),
|
||||||
};
|
};
|
||||||
|
/* since we have a literal return value, we want it to be fully treated like one by the memory manager */
|
||||||
|
make_value_statically_allocated(&func_ident->tok.Val);
|
||||||
|
/* immediately free any heap-allocated literals that are no longer needed */
|
||||||
|
for (size_t i = 0; i < args_len; i++)
|
||||||
|
free_value(&arg_vals[i], true);
|
||||||
|
/* free buffers */
|
||||||
if (arg_vals)
|
if (arg_vals)
|
||||||
free(arg_vals);
|
free(arg_vals);
|
||||||
if (args)
|
if (args)
|
||||||
|
Loading…
Reference in New Issue
Block a user