support for builtin functions with 0 args
This commit is contained in:
parent
ca232fbf6a
commit
9bd4d4e0c4
2
ir.c
2
ir.c
@ -43,7 +43,7 @@ void irtoks_init_short(IRToks *v) {
|
|||||||
|
|
||||||
void irtoks_term(IRToks *v) {
|
void irtoks_term(IRToks *v) {
|
||||||
for (size_t i = 0; i < v->len; i++) {
|
for (size_t i = 0; i < v->len; i++) {
|
||||||
if (v->toks[i].instr == IRCallInternal)
|
if (v->toks[i].instr == IRCallInternal && v->toks[i].CallI.args)
|
||||||
free(v->toks[i].CallI.args);
|
free(v->toks[i].CallI.args);
|
||||||
}
|
}
|
||||||
free(v->toks);
|
free(v->toks);
|
||||||
|
61
parse.c
61
parse.c
@ -242,29 +242,37 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
|
|||||||
bool eval_func_in_place = !func.side_effects;
|
bool eval_func_in_place = !func.side_effects;
|
||||||
|
|
||||||
size_t args_len = 0;
|
size_t args_len = 0;
|
||||||
size_t args_cap = 16;
|
IRParam *args = NULL;
|
||||||
IRParam *args = xmalloc(sizeof(IRParam) * args_cap);
|
|
||||||
for (;;) {
|
if (t->next->tok.kind == TokOp && t->next->tok.Op == OpRParen) {
|
||||||
if (args_len+1 > args_cap)
|
/* no args */
|
||||||
args = xrealloc(args, (args_cap *= 2));
|
toklist_del(toks, t->next, t->next); /* delete right parenthesis */
|
||||||
IRParam a;
|
} else {
|
||||||
TRY_RET_ELSE(a = expr_into_irparam(out_ir, toks, funcs, &sc, t->next), (ExprRet){0}, free(args));
|
/* go through the arguments, evaluate them and put them into the args array */
|
||||||
args[args_len++] = a;
|
size_t args_cap = 16;
|
||||||
if (a.kind != IRParamLiteral)
|
args = xmalloc(sizeof(IRParam) * args_cap);
|
||||||
eval_func_in_place = false;
|
for (;;) {
|
||||||
if (t->next->tok.kind == TokOp) {
|
if (args_len+1 > args_cap)
|
||||||
if (t->next->tok.Op == OpComma) {
|
args = xrealloc(args, (args_cap *= 2));
|
||||||
toklist_del(toks, t->next, t->next);
|
IRParam a;
|
||||||
continue;
|
TRY_RET_ELSE(a = expr_into_irparam(out_ir, toks, funcs, &sc, t->next), (ExprRet){0}, free(args));
|
||||||
} else if (t->next->tok.Op == OpRParen) {
|
args[args_len++] = a;
|
||||||
toklist_del(toks, t->next, t->next);
|
if (a.kind != IRParamLiteral)
|
||||||
break;
|
eval_func_in_place = false;
|
||||||
|
if (t->next->tok.kind == TokOp) {
|
||||||
|
if (t->next->tok.Op == OpComma) {
|
||||||
|
toklist_del(toks, t->next, t->next); /* delete right parenthesis */
|
||||||
|
continue;
|
||||||
|
} else if (t->next->tok.Op == OpRParen) {
|
||||||
|
toklist_del(toks, t->next, t->next); /* delete right parenthesis */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mark_err(&t->next->tok);
|
||||||
|
set_err("Expected ',' or ')' after function argument");
|
||||||
|
free(args);
|
||||||
|
return (ExprRet){0};
|
||||||
}
|
}
|
||||||
mark_err(&t->next->tok);
|
|
||||||
set_err("Expected ',' or ')' after function argument");
|
|
||||||
free(args);
|
|
||||||
return (ExprRet){0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t = func_ident;
|
t = func_ident;
|
||||||
@ -274,21 +282,24 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc,
|
|||||||
mark_err(&func_ident->tok);
|
mark_err(&func_ident->tok);
|
||||||
const char *plural = func.n_args == 1 ? "" : "s";
|
const char *plural = func.n_args == 1 ? "" : "s";
|
||||||
set_err("Function %s() takes %zu argument%s but got %zu", func.name, func.n_args, plural, args_len);
|
set_err("Function %s() takes %zu argument%s but got %zu", func.name, func.n_args, plural, args_len);
|
||||||
free(args);
|
if (args)
|
||||||
|
free(args);
|
||||||
return (ExprRet){0};
|
return (ExprRet){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eval_func_in_place) {
|
if (eval_func_in_place) {
|
||||||
/* evaluate the function in place */
|
/* evaluate the function in place */
|
||||||
Value *arg_vals = xmalloc(sizeof(Value) * args_len);
|
Value *arg_vals = args_len ? xmalloc(sizeof(Value) * args_len) : NULL;
|
||||||
for (size_t i = 0; i < args_len; i++)
|
for (size_t i = 0; i < args_len; i++)
|
||||||
arg_vals[i] = args[i].Literal;
|
arg_vals[i] = args[i].Literal;
|
||||||
func_ident->tok = (Tok) {
|
func_ident->tok = (Tok) {
|
||||||
.kind = TokVal,
|
.kind = TokVal,
|
||||||
.Val = func.func(arg_vals),
|
.Val = func.func(arg_vals),
|
||||||
};
|
};
|
||||||
free(arg_vals);
|
if (arg_vals)
|
||||||
free(args);
|
free(arg_vals);
|
||||||
|
if (args)
|
||||||
|
free(args);
|
||||||
} else {
|
} else {
|
||||||
bool is_last_operation = t == start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM;
|
bool is_last_operation = t == start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user