Implement function definitions
This commit is contained in:
parent
6789984bd1
commit
d6d2b228ef
@ -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;
|
||||||
|
41
src/cg.c
41
src/cg.c
@ -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;
|
||||||
}
|
}
|
||||||
|
33
src/parse.c
33
src/parse.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
src/types.c
16
src/types.c
@ -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. */
|
||||||
|
Loading…
Reference in New Issue
Block a user