Implement function definitions

This commit is contained in:
Mid 2024-11-26 18:42:20 +02:00
parent 6789984bd1
commit d6d2b228ef
4 changed files with 81 additions and 17 deletions

View File

@ -42,6 +42,7 @@
K(AST_EXPR_STRING_LITERAL) \ K(AST_EXPR_STRING_LITERAL) \
K(AST_EXPR_CAST) \ K(AST_EXPR_CAST) \
K(AST_EXPR_ARRAY) \ K(AST_EXPR_ARRAY) \
K(AST_EXPR_FUNC) \
K(AST_STMT_EXT_ORG) \ K(AST_STMT_EXT_ORG) \
K(AST_STMT_EXT_SECTION) K(AST_STMT_EXT_SECTION)
@ -136,6 +137,12 @@ typedef struct {
ASTExpr; ASTExpr;
} ASTExprStackPointer; } ASTExprStackPointer;
typedef struct {
ASTExpr;
union AST *chunk;
} ASTExprFunc;
typedef struct { typedef struct {
ASTKind nodeKind; ASTKind nodeKind;
@ -271,6 +278,7 @@ typedef union AST {
ASTExprStringLiteral exprStrLit; ASTExprStringLiteral exprStrLit;
ASTExprCast exprCast; ASTExprCast exprCast;
ASTExprArray exprArray; ASTExprArray exprArray;
ASTExprFunc exprFunc;
ASTStmtExtOrg stmtExtOrg; ASTStmtExtOrg stmtExtOrg;
ASTStmtExtSection stmtExtSection; ASTStmtExtSection stmtExtSection;
} AST; } AST;

View File

@ -20,10 +20,12 @@ static const char *BINOP_SIMPLE_INSTRS[] = {[BINOP_ADD] = "add", [BINOP_SUB] = "
static size_t nextLocalLabel = 0; static size_t nextLocalLabel = 0;
typedef struct {
#define LOOPSTACKSIZE 96 #define LOOPSTACKSIZE 96
static size_t loopStackStart[LOOPSTACKSIZE]; size_t loopStackStart[LOOPSTACKSIZE];
static size_t loopStackEnd[LOOPSTACKSIZE]; size_t loopStackEnd[LOOPSTACKSIZE];
static size_t loopStackIdx; size_t loopStackIdx;
} CGState;
static const char *direct(int size) { static const char *direct(int size) {
switch(size) { switch(size) {
@ -150,7 +152,7 @@ static const char *xop(AST *e) {
return xop_sz(e, type_size(e->expression.type)); 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; AST *s = a->chunk.statementFirst;
if(a->chunk.stackReservation) { if(a->chunk.stackReservation) {
@ -203,7 +205,15 @@ void cg_chunk(AST *a) {
printf("%i,", s->stmtDecl.expression->exprArray.items[i]->exprPrim.val); 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'); putchar('\n');
} else { } else {
@ -298,27 +308,27 @@ void cg_chunk(AST *a) {
size_t lbl0 = nextLocalLabel++; size_t lbl0 = nextLocalLabel++;
size_t lbl1 = nextLocalLabel++; size_t lbl1 = nextLocalLabel++;
loopStackStart[loopStackIdx] = lbl0; cg->loopStackStart[cg->loopStackIdx] = lbl0;
loopStackEnd[loopStackIdx] = lbl1; cg->loopStackEnd[cg->loopStackIdx] = lbl1;
loopStackIdx++; cg->loopStackIdx++;
printf(".L%lu:\n", lbl0); printf(".L%lu:\n", lbl0);
cg_chunk(s->stmtLoop.body); cg_chunk(cg, s->stmtLoop.body);
printf("jmp .L%lu\n", lbl0); printf("jmp .L%lu\n", lbl0);
printf(".L%lu:\n", lbl1); printf(".L%lu:\n", lbl1);
loopStackIdx--; cg->loopStackIdx--;
} else if(s->nodeKind == AST_STMT_BREAK) { } 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) { } 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) { } 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("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); 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); printf(".L%lu:\n", lbl);
@ -531,7 +541,10 @@ nextColor:;
return 0; return 0;
} }
cg_chunk(a); CGState cg;
memset(&cg, 0, sizeof(cg));
cg_chunk(&cg, a);
return 1; return 1;
} }

View File

@ -237,7 +237,30 @@ AST *nct_cast_expr(AST *what, Type *to) {
abort(); abort();
} }
ASTChunk *nct_parse_chunk(Parser*, int, int);
Type *nct_parse_typename(Parser *P);
AST *nct_parse_expression(Parser *P, int lOP) { 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(lOP == 5) {
if(peek(P, 0).type == TOKEN_NUMBER) { if(peek(P, 0).type == TOKEN_NUMBER) {
return (AST*) parse_prim(P); return (AST*) parse_prim(P);
@ -714,7 +737,6 @@ backtrack:
return NULL; return NULL;
} }
ASTChunk *nct_parse_chunk(Parser*, int, int);
void nct_parse_statement(Parser *P) { void nct_parse_statement(Parser *P) {
if(maybe(P, TOKEN_IF)) { if(maybe(P, TOKEN_IF)) {
expect(P, TOKEN_PAREN_L); 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); P->scope = vartable_new(P->scope);
ASTChunk *oldTopLevel = P->topLevel;
if(isTopLevel) { if(isTopLevel) {
P->topLevel = &ret->chunk; P->topLevel = &ret->chunk;
} }
@ -923,7 +946,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) {
/* Move back to beginning of declaration. */ /* Move back to beginning of declaration. */
do { do {
P->i--; 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++; P->i++;
AST *d = parse_declaration(P); AST *d = parse_declaration(P);
@ -937,7 +960,7 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) {
/* Now actual parsing. */ /* 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); nct_parse_statement(P);
} }
@ -965,6 +988,10 @@ ASTChunk *nct_parse_chunk(Parser *P, int isTopLevel, int varPrioritize) {
P->currentChunk = oldChunk; P->currentChunk = oldChunk;
if(isTopLevel) {
P->topLevel = oldTopLevel;
}
return &ret->chunk; return &ret->chunk;
} }

View File

@ -117,6 +117,22 @@ int type_equal(Type *O, Type *T) {
return type_equal(O->pointer.of, T->pointer.of); return type_equal(O->pointer.of, T->pointer.of);
} else if(O->type == TYPE_TYPE_ARRAY) { } else if(O->type == TYPE_TYPE_ARRAY) {
return type_equal(O->array.of, T->array.of) && O->array.length == T->array.length; 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. */ /* Consider nominal typing. */