feat: implement functions
This commit is contained in:
+101
-1
@@ -514,6 +514,79 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (type->type == FZL_TOKTYPE_TYPE)
|
||||
consume(parser);
|
||||
|
||||
if (type->type == FZL_TOKTYPE_TYPE &&
|
||||
next(parser)->type == FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
fzl_token_t *tok = consume(parser);
|
||||
if (tok->type != FZL_TOKTYPE_NAME)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected name in function definition at %ld:%ld", tok->ln,
|
||||
tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_token_t *lparen = consume(parser);
|
||||
if (lparen->type != FZL_TOKTYPE_LPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected '(' after name at %ld:%ld", lparen->ln, lparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t remainder = 1;
|
||||
size_t count = 0;
|
||||
fzl_node_t **args = malloc(remainder * sizeof(fzl_node_t *));
|
||||
|
||||
while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN))
|
||||
{
|
||||
fzl_node_t *arg = parse_statement(parser);
|
||||
if (!arg)
|
||||
return NULL;
|
||||
|
||||
if (remainder <= count)
|
||||
{
|
||||
remainder *= 2;
|
||||
args = realloc(args, remainder * sizeof(fzl_node_t *));
|
||||
}
|
||||
|
||||
args[count++] = arg;
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_COMMA))
|
||||
consume(parser);
|
||||
}
|
||||
|
||||
fzl_token_t *rparen = consume(parser);
|
||||
if (rparen->type != FZL_TOKTYPE_RPAREN)
|
||||
{
|
||||
snprintf(plast_err, sizeof(plast_err),
|
||||
"expected ')' after argument list at %ld:%ld", rparen->ln,
|
||||
rparen->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!is(parser, FZL_TOKTYPE_LBRACE))
|
||||
{
|
||||
fzl_token_t *tok = peek(parser);
|
||||
snprintf(plast_err, sizeof(plast_err), "expected '{' at %ld:%ld",
|
||||
tok->ln, tok->cn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fzl_node_t *body = parse_statement(parser);
|
||||
if (!body)
|
||||
return NULL;
|
||||
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_FUNCTION, tok);
|
||||
node->fn.args = args;
|
||||
node->fn.args_count = count;
|
||||
node->fn.body = body;
|
||||
node->fn.name = tok;
|
||||
node->fn.type = type;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
if (type->type == FZL_TOKTYPE_TYPE || next(parser)->type == FZL_TOKTYPE_EQ)
|
||||
{
|
||||
|
||||
@@ -574,6 +647,25 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
return left;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_RETURN))
|
||||
{
|
||||
fzl_token_t *ret = consume(parser);
|
||||
fzl_node_t *node = fzl_mknode(FZL_NODETYPE_RETURN, ret);
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_DOT))
|
||||
{
|
||||
consume(parser);
|
||||
return node;
|
||||
}
|
||||
|
||||
fzl_node_t *retval = parse_expression(parser);
|
||||
if (!retval)
|
||||
return NULL;
|
||||
|
||||
node->ret.value = retval;
|
||||
return node;
|
||||
}
|
||||
|
||||
if (is(parser, FZL_TOKTYPE_IF))
|
||||
{
|
||||
fzl_token_t *if_tok = consume(parser);
|
||||
@@ -637,7 +729,7 @@ fzl_node_t *parse_statement(fzl_parser_t *parser)
|
||||
if (remainder <= count)
|
||||
{
|
||||
remainder *= 2;
|
||||
stmts = realloc(stmts, remainder);
|
||||
stmts = realloc(stmts, remainder * sizeof(fzl_node_t *));
|
||||
}
|
||||
|
||||
stmts[count++] = node;
|
||||
@@ -758,6 +850,14 @@ void fzl_freeast(fzl_node_t *root)
|
||||
if (root->unary_op.operand)
|
||||
fzl_freeast(root->unary_op.operand);
|
||||
}
|
||||
else if (root->type == FZL_NODETYPE_FUNCTION)
|
||||
{
|
||||
if (root->fn.args_count)
|
||||
for (size_t i = 0; i < root->fn.args_count; i++)
|
||||
fzl_freenode(root->fn.args[i]);
|
||||
free(root->fn.args);
|
||||
fzl_freenode(root->fn.body);
|
||||
}
|
||||
|
||||
fzl_freenode(root);
|
||||
root = root->next;
|
||||
|
||||
Reference in New Issue
Block a user