summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorCarson Fleming <[email protected]>2026-03-29 08:28:28 -1000
committerCarson Fleming <[email protected]>2026-03-29 08:28:28 -1000
commit7cf2065be92855b5b1db31a4bb7afbb4af29a817 (patch)
tree773e9df00d46934f548a2d76dbe6e61aec9b21c9 /parser.c
parent50495e8f815d3d5f92b3d36369acc52a6d2ea9c4 (diff)
downloadccc-7cf2065be92855b5b1db31a4bb7afbb4af29a817.tar.gz
calling functions and some optimizationsHEADmaster
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c81
1 files changed, 58 insertions, 23 deletions
diff --git a/parser.c b/parser.c
index 157ffb1..f9c7047 100644
--- a/parser.c
+++ b/parser.c
@@ -63,11 +63,14 @@ static void expect_kw(const char* kw) {
}
static void parse_type(struct type_node* p_node) {
- /* TODO: need some concept of known types in scope */
/* TODO: modifiers, void rules, arrays, etc. */
/* TODO: struct, union, enum */
expect(TK_IDENT);
- p_node->name = tok.data.ident;
+ struct type_def type_def;
+ if (!scope_get_type(scope, &type_def, tok.data.ident))
+ PARSER_PANIC("unknown type name: %s", tok.data.ident);
+
+ p_node->def = type_def;
peek_or_panic();
p_node->ptr_level = 0;
@@ -118,9 +121,6 @@ static void expr_to_lval(struct lval_node* l_node, struct expr_node* e_node) {
}
static void parse_expr_assign(struct expr_node* p_node) {
- peek_or_panic();
- if (tok.type != TK_ASSIGN) return;
-
expr_to_lval(&p_node->as._assign.lval, p_node);
p_node->type = EXPR_ASSIGN;
p_node->as._assign.rval = protected_alloc(sizeof(struct expr_node));
@@ -129,6 +129,44 @@ static void parse_expr_assign(struct expr_node* p_node) {
parse_expr(p_node->as._assign.rval);
}
+static void parse_arg_evals(struct expr_node** pp_arg) {
+ for (;;) {
+ *pp_arg = protected_alloc(sizeof(struct expr_node));
+ parse_expr(*pp_arg);
+ pp_arg = &((*pp_arg)->next);
+
+ peek_or_panic();
+ if (tok.type == TK_RPAREN) break;
+ expect(TK_COMMA);
+ }
+}
+
+static void parse_expr_call(struct expr_node* p_node) {
+ switch (p_node->type) {
+ case EXPR_VAR_REF:
+ struct var_def var_def;
+ if (!scope_get_var(scope, &var_def, p_node->as._var_ref.ident))
+ PARSER_PANIC(
+ "%s is not a known function", p_node->as._var_ref.ident);
+
+ if (var_def.loc.type != STO_FN)
+ PARSER_PANIC("called object is not a function");
+
+ p_node->as._call.called_fn = var_def.loc.decl;
+ break;
+ default:
+ PARSER_PANIC("expression is not callable");
+ }
+
+ p_node->type = EXPR_CALL;
+ p_node->as._call.args_head = NULL;
+
+ expect(TK_LPAREN);
+ peek_or_panic();
+ if (tok.type != TK_RPAREN) parse_arg_evals(&p_node->as._call.args_head);
+ expect(TK_RPAREN);
+}
+
static void parse_expr(struct expr_node* p_node) {
peek_or_panic();
switch (tok.type) {
@@ -146,27 +184,16 @@ static void parse_expr(struct expr_node* p_node) {
case TK_IDENT:
p_node->type = EXPR_VAR_REF;
parse_var_ref(&p_node->as._var_ref);
-
- peek_or_panic();
- if (tok.type == TK_ASSIGN) {
- p_node->type = EXPR_ASSIGN;
- p_node->as._assign = (struct assign_node) {
- .lval = {
- .type = LVAL_VAR_REF,
- .as._var_ref = p_node->as._var_ref,
- },
- .rval = protected_alloc(sizeof(struct expr_node)),
- };
-
- expect(TK_ASSIGN);
- parse_expr(p_node->as._assign.rval);
- }
break;
default:
PARSER_PANIC("expected expression");
}
- parse_expr_assign(p_node);
+ peek_or_panic();
+ if (tok.type == TK_ASSIGN)
+ parse_expr_assign(p_node);
+ else if (tok.type == TK_LPAREN)
+ parse_expr_call(p_node);
}
static void parse_var_decl(struct var_decl_node* p_node) {
@@ -259,7 +286,7 @@ static void parse_stmt(struct stmt_node* p_node) {
expect(TK_SEMI);
}
-static void parse_arg_list(struct var_decl_node** pp_arg) {
+static void parse_arg_decls(struct var_decl_node** pp_arg) {
for (;;) {
*pp_arg = protected_alloc(sizeof(struct var_decl_node));
parse_var_decl(*pp_arg);
@@ -280,11 +307,19 @@ static void parse_fn_decl(struct fn_decl_node* p_node) {
expect(TK_LPAREN);
peek_or_panic();
- if (tok.type != TK_RPAREN) parse_arg_list(&p_node->args_head);
+ if (tok.type != TK_RPAREN) parse_arg_decls(&p_node->args_head);
expect(TK_RPAREN);
parse_group(&p_node->body);
+
+ scope_define_var(scope, (struct var_def) {
+ .name = p_node->name,
+ .loc = {
+ .type = STO_FN,
+ .decl = p_node,
+ },
+ });
}
static bool parse_root(struct root_node* p_node) {