#include #include #include #include #include // Parse external function fzl_node_t *pa_externfn(fzl_parser_t *parser) { if (!parser || !peek(parser)) return NULL; fzl_token_t *tok = consume(parser); if (!tok || tok->type != FZL_TOKTYPE_FUNCTION) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected 'function' keyword", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_token_t *name = consume(parser); if (!name || name->type != FZL_TOKTYPE_NAME) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected function name after 'fn'", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } fzl_token_t *lpar = consume(parser); if (!lpar || lpar->type != FZL_TOKTYPE_LPAREN) { snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected '(' after function name", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } size_t remainder = 2; size_t count = 0; fzl_node_t **args = malloc(remainder * sizeof(fzl_node_t *)); if (!args) { snprintf(plast_err, sizeof(plast_err), "out of memory"); return NULL; } while (peek(parser) && !is(parser, FZL_TOKTYPE_RPAREN)) { if (remainder <= count) { remainder *= 2; fzl_node_t **newarr = realloc(args, remainder * sizeof(fzl_node_t *)); if (!newarr) { for (size_t i = 0; i < count; i++) fzl_freeast(args[i]); free(args); snprintf(plast_err, sizeof(plast_err), "out of memory"); return NULL; } args = newarr; } bool is_out = false; if (is(parser, FZL_TOKTYPE_OUT)) { consume(parser); is_out = true; } fzl_node_t *node = pa_expression(parser); if (!node || node->type != FZL_NODETYPE_DECLARATION) { for (size_t i = 0; i < count; i++) fzl_freeast(args[i]); free(args); if (!plast_err[0]) snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected declaration", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } node->var.is_out = is_out; args[count++] = node; if (is(parser, FZL_TOKTYPE_RPAREN)) break; fzl_token_t *comma = consume(parser); if (!comma || comma->type != FZL_TOKTYPE_COMMA) { for (size_t i = 0; i < count; i++) fzl_freeast(args[i]); free(args); snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => missing ',' between arguments", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } } fzl_token_t *rpar = consume(parser); if (!rpar || rpar->type != FZL_TOKTYPE_RPAREN) { for (size_t i = 0; i < count; i++) fzl_freeast(args[i]); free(args); snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected ')' after arguments list", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } char *original_name = NULL; fzl_token_t *type = &null_tok; if (is(parser, FZL_TOKTYPE_NAME) || is(parser, FZL_TOKTYPE_TYPE)) type = consume(parser); if (is(parser, FZL_TOKTYPE_EQ)) { consume(parser); fzl_token_t *orig = consume(parser); if (!orig || orig->type != FZL_TOKTYPE_STR_LITERAL) { for (size_t i = 0; i < count; i++) fzl_freeast(args[i]); free(args); snprintf(plast_err, sizeof(plast_err), "'%s':%zu:%zu => expected original function name", last_known_tok->filename, last_known_tok->ln, last_known_tok->cn); return NULL; } original_name = (char *)orig->value; } fzl_node_t *node = fzl_mknode(FZL_NODETYPE_EXTERN_FN, tok); node->ext_fn.name = (char *)name->value; node->ext_fn.original_name = original_name; node->ext_fn.args_count = count; node->ext_fn.args = args; node->ext_fn.type = type; return node; }