From d6d2b228ef73d1dbbaf828ee5f7d2994ec6e3752 Mon Sep 17 00:00:00 2001 From: Mid <> Date: Tue, 26 Nov 2024 18:42:20 +0200 Subject: [PATCH] Implement function definitions --- src/ast.h | 8 ++++++++ src/cg.c | 41 +++++++++++++++++++++++++++-------------- src/parse.c | 33 ++++++++++++++++++++++++++++++--- src/types.c | 16 ++++++++++++++++ 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/src/ast.h b/src/ast.h index 8749f38..cb5a38c 100644 --- a/src/ast.h +++ b/src/ast.h @@ -42,6 +42,7 @@ K(AST_EXPR_STRING_LITERAL) \ K(AST_EXPR_CAST) \ K(AST_EXPR_ARRAY) \ + K(AST_EXPR_FUNC) \ K(AST_STMT_EXT_ORG) \ K(AST_STMT_EXT_SECTION) @@ -136,6 +137,12 @@ typedef struct { ASTExpr; } ASTExprStackPointer; +typedef struct { + ASTExpr; + + union AST *chunk; +} ASTExprFunc; + typedef struct { ASTKind nodeKind; @@ -271,6 +278,7 @@ typedef union AST { ASTExprStringLiteral exprStrLit; ASTExprCast exprCast; ASTExprArray exprArray; + ASTExprFunc exprFunc; ASTStmtExtOrg stmtExtOrg; ASTStmtExtSection stmtExtSection; } AST; diff --git a/src/cg.c b/src/cg.c index 8249236..de49b41 100644 --- a/src/cg.c +++ b/src/cg.c @@ -20,10 +20,12 @@ static const char *BINOP_SIMPLE_INSTRS[] = {[BINOP_ADD] = "add", [BINOP_SUB] = " static size_t nextLocalLabel = 0; +typedef struct { #define LOOPSTACKSIZE 96 -static size_t loopStackStart[LOOPSTACKSIZE]; -static size_t loopStackEnd[LOOPSTACKSIZE]; -static size_t loopStackIdx; + size_t loopStackStart[LOOPSTACKSIZE]; + size_t loopStackEnd[LOOPSTACKSIZE]; + size_t loopStackIdx; +} CGState; static const char *direct(int size) { switch(size) { @@ -150,7 +152,7 @@ static const char *xop(AST *e) { return xop_sz(e, type_size(e->expression.type)); } -void cg_chunk(AST *a) { +void cg_chunk(CGState *cg, AST *a) { AST *s = a->chunk.statementFirst; if(a->chunk.stackReservation) { @@ -203,7 +205,15 @@ void cg_chunk(AST *a) { printf("%i,", s->stmtDecl.expression->exprArray.items[i]->exprPrim.val); } - } else printf("A"); + } else if(v->type->type == TYPE_TYPE_FUNCTION) { + + putchar('\n'); + + assert(s->stmtDecl.expression->nodeKind == AST_EXPR_FUNC); + + cg_go(s->stmtDecl.expression->exprFunc.chunk); + + } else abort(); putchar('\n'); } else { @@ -298,27 +308,27 @@ void cg_chunk(AST *a) { size_t lbl0 = nextLocalLabel++; size_t lbl1 = nextLocalLabel++; - loopStackStart[loopStackIdx] = lbl0; - loopStackEnd[loopStackIdx] = lbl1; - loopStackIdx++; + cg->loopStackStart[cg->loopStackIdx] = lbl0; + cg->loopStackEnd[cg->loopStackIdx] = lbl1; + cg->loopStackIdx++; printf(".L%lu:\n", lbl0); - cg_chunk(s->stmtLoop.body); + cg_chunk(cg, s->stmtLoop.body); printf("jmp .L%lu\n", lbl0); printf(".L%lu:\n", lbl1); - loopStackIdx--; + cg->loopStackIdx--; } else if(s->nodeKind == AST_STMT_BREAK) { - printf("jmp .L%lu\n", loopStackEnd[loopStackIdx - 1]); + printf("jmp .L%lu\n", cg->loopStackEnd[cg->loopStackIdx - 1]); } else if(s->nodeKind == AST_STMT_CONTINUE) { - printf("jmp .L%lu\n", loopStackStart[loopStackIdx - 1]); + printf("jmp .L%lu\n", cg->loopStackStart[cg->loopStackIdx - 1]); } else if(s->nodeKind == AST_STMT_IF) { @@ -329,7 +339,7 @@ void cg_chunk(AST *a) { printf("cmp %s, %s\n", xop(s->stmtIf.expression->exprBinOp.operands[0]), xop(s->stmtIf.expression->exprBinOp.operands[1])); printf("j%s .L%lu\n", xj(binop_comp_opposite(s->stmtIf.expression->exprBinOp.operator)), lbl); - cg_chunk(s->stmtIf.then); + cg_chunk(cg, s->stmtIf.then); printf(".L%lu:\n", lbl); @@ -531,7 +541,10 @@ nextColor:; return 0; } - cg_chunk(a); + CGState cg; + memset(&cg, 0, sizeof(cg)); + + cg_chunk(&cg, a); return 1; } diff --git a/src/parse.c b/src/parse.c index 3426c9c..63e615b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -237,7 +237,30 @@ AST *nct_cast_expr(AST *what, Type *to) { abort(); } +ASTChunk *nct_parse_chunk(Parser*, int, int); +Type *nct_parse_typename(Parser *P); + AST *nct_parse_expression(Parser *P, int lOP) { + if(lOP == 0) { + // Test if this is an anonymous function + Type *ft = nct_parse_typename(P); + if(ft) { + assert(ft->type == TYPE_TYPE_FUNCTION); + + ASTExprFunc *e = malloc(sizeof(*e)); + e->nodeKind = AST_EXPR_FUNC; + e->type = ft; + + maybe(P, TOKEN_SQUIGGLY_L); + + e->chunk = (AST*) nct_parse_chunk(P, 1, 0); + + maybe(P, TOKEN_SQUIGGLY_R); + + return (AST*) e; + } + } + if(lOP == 5) { if(peek(P, 0).type == TOKEN_NUMBER) { return (AST*) parse_prim(P); @@ -714,7 +737,6 @@ backtrack: return NULL; } -ASTChunk *nct_parse_chunk(Parser*, int, int); void nct_parse_statement(Parser *P) { if(maybe(P, TOKEN_IF)) { expect(P, TOKEN_PAREN_L); @@ -893,6 +915,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { P->scope = vartable_new(P->scope); + ASTChunk *oldTopLevel = P->topLevel; if(isTopLevel) { P->topLevel = &ret->chunk; } @@ -923,7 +946,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { /* Move back to beginning of declaration. */ do { P->i--; - } while(P->i >= 0 && P->tokens[P->i].type != TOKEN_SEMICOLON && P->tokens[P->i].type != TOKEN_SQUIGGLY_R && P->tokens[P->i].type != TOKEN_PAREN_R); + } while(P->i >= 0 && P->tokens[P->i].type != TOKEN_SEMICOLON && P->tokens[P->i].type != TOKEN_SQUIGGLY_R); P->i++; AST *d = parse_declaration(P); @@ -937,7 +960,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { /* Now actual parsing. */ - while(peek(P, 0).type != (isTopLevel ? TOKEN_EOF : TOKEN_SQUIGGLY_R)) { + while(peek(P, 0).type != TOKEN_EOF && peek(P, 0).type != TOKEN_SQUIGGLY_R) { nct_parse_statement(P); } @@ -965,6 +988,10 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) { P->currentChunk = oldChunk; + if(isTopLevel) { + P->topLevel = oldTopLevel; + } + return &ret->chunk; } diff --git a/src/types.c b/src/types.c index e4894f4..5702a17 100644 --- a/src/types.c +++ b/src/types.c @@ -117,6 +117,22 @@ int type_equal(Type *O, Type *T) { return type_equal(O->pointer.of, T->pointer.of); } else if(O->type == TYPE_TYPE_ARRAY) { return type_equal(O->array.of, T->array.of) && O->array.length == T->array.length; + } else if(O->type == TYPE_TYPE_FUNCTION) { + if(!type_equal(O->function.ret, T->function.ret)) { + return 0; + } + + if(O->function.argCount != T->function.argCount) { + return 0; + } + + for(int i = 0; i < O->function.argCount; i++) { + if(!type_equal(O->function.args[i], T->function.args[i])) { + return 0; + } + } + + return 1; } /* Consider nominal typing. */