Add return statement
This commit is contained in:
parent
8caadf9af1
commit
390c4c954d
39
src/ast.c
39
src/ast.c
@ -309,6 +309,10 @@ static void ast_usedef_pass(AST *tlc, AST *a, AST *wholestmt) {
|
|||||||
} else if(a->nodeKind == AST_STMT_EXT_SECTION) {
|
} else if(a->nodeKind == AST_STMT_EXT_SECTION) {
|
||||||
} else if(a->nodeKind == AST_STMT_DECL) {
|
} else if(a->nodeKind == AST_STMT_DECL) {
|
||||||
assert(a->stmtDecl.thing->kind != VARTABLEENTRY_VAR || a->stmtDecl.expression);
|
assert(a->stmtDecl.thing->kind != VARTABLEENTRY_VAR || a->stmtDecl.expression);
|
||||||
|
} else if(a->nodeKind == AST_STMT_RETURN) {
|
||||||
|
if(a->stmtReturn.val) {
|
||||||
|
ast_usedef_pass(tlc, a->stmtReturn.val, wholestmt);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@ -447,6 +451,32 @@ static char *ast_dumpe(AST *e) {
|
|||||||
return r;
|
return r;
|
||||||
} else if(e->nodeKind == AST_EXPR_STACK_POINTER) {
|
} else if(e->nodeKind == AST_EXPR_STACK_POINTER) {
|
||||||
return malp("@stack");
|
return malp("@stack");
|
||||||
|
} else if(e->nodeKind == AST_EXPR_FUNC) {
|
||||||
|
char *out = NULL;
|
||||||
|
|
||||||
|
{
|
||||||
|
char *rettype = type_to_string(e->expression.type->function.ret);
|
||||||
|
out = malp("%s(", rettype);
|
||||||
|
free(rettype);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < e->expression.type->function.argCount; i++) {
|
||||||
|
char *argtype = type_to_string(e->expression.type->function.args[i]);
|
||||||
|
char *out2 = malp(i == e->expression.type->function.argCount - 1 ? "%s%s" : "%s%s, ", out, argtype);
|
||||||
|
free(out);
|
||||||
|
free(argtype);
|
||||||
|
out = out2;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char *choonk = ast_dump(e->exprFunc.chunk);
|
||||||
|
char *out2 = malp("%s) {\n%s}", out, choonk);
|
||||||
|
free(out);
|
||||||
|
free(choonk);
|
||||||
|
out = out2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
return malp("@unimp:%s", AST_KIND_STR[e->nodeKind]);
|
||||||
@ -495,6 +525,15 @@ static char *ast_dumps(AST *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return malp("%s; /* loop guard */\n", name);
|
return malp("%s; /* loop guard */\n", name);
|
||||||
|
} else if(s->nodeKind == AST_STMT_RETURN) {
|
||||||
|
if(s->stmtReturn.val) {
|
||||||
|
char *e = ast_dumpe(s->stmtReturn.val);
|
||||||
|
char *c = malp("return %s;\n", e);
|
||||||
|
free(e);
|
||||||
|
return c;
|
||||||
|
} else {
|
||||||
|
return malp("return;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return malp("@unimp:%s\n", AST_KIND_STR[s->nodeKind]);
|
return malp("@unimp:%s\n", AST_KIND_STR[s->nodeKind]);
|
||||||
|
10
src/ast.h
10
src/ast.h
@ -44,7 +44,8 @@
|
|||||||
K(AST_EXPR_ARRAY) \
|
K(AST_EXPR_ARRAY) \
|
||||||
K(AST_EXPR_FUNC) \
|
K(AST_EXPR_FUNC) \
|
||||||
K(AST_STMT_EXT_ORG) \
|
K(AST_STMT_EXT_ORG) \
|
||||||
K(AST_STMT_EXT_SECTION)
|
K(AST_STMT_EXT_SECTION) \
|
||||||
|
K(AST_STMT_RETURN)
|
||||||
|
|
||||||
typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind;
|
typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind;
|
||||||
extern const char *AST_KIND_STR[];
|
extern const char *AST_KIND_STR[];
|
||||||
@ -256,6 +257,12 @@ typedef struct {
|
|||||||
Token name;
|
Token name;
|
||||||
} ASTStmtExtSection;
|
} ASTStmtExtSection;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASTStmt;
|
||||||
|
|
||||||
|
union AST *val;
|
||||||
|
} ASTStmtReturn;
|
||||||
|
|
||||||
typedef union AST {
|
typedef union AST {
|
||||||
ASTKind nodeKind;
|
ASTKind nodeKind;
|
||||||
|
|
||||||
@ -268,6 +275,7 @@ typedef union AST {
|
|||||||
ASTStmtContinue stmtContinue;
|
ASTStmtContinue stmtContinue;
|
||||||
ASTStmtExpr stmtExpr;
|
ASTStmtExpr stmtExpr;
|
||||||
ASTStmtAssign stmtAssign;
|
ASTStmtAssign stmtAssign;
|
||||||
|
ASTStmtReturn stmtReturn;
|
||||||
ASTExpr expression;
|
ASTExpr expression;
|
||||||
ASTExprPrimitive exprPrim;
|
ASTExprPrimitive exprPrim;
|
||||||
ASTExprBinaryOp exprBinOp;
|
ASTExprBinaryOp exprBinOp;
|
||||||
|
12
src/cg.c
12
src/cg.c
@ -343,7 +343,17 @@ void cg_chunk(CGState *cg, AST *a) {
|
|||||||
|
|
||||||
printf(".L%lu:\n", lbl);
|
printf(".L%lu:\n", lbl);
|
||||||
|
|
||||||
}
|
} else if(s->nodeKind == AST_STMT_RETURN) {
|
||||||
|
|
||||||
|
if(s->stmtReturn.val) {
|
||||||
|
assert(s->stmtReturn.val->nodeKind == AST_EXPR_VAR);
|
||||||
|
assert(s->stmtReturn.val->exprVar.thing->kind == VARTABLEENTRY_VAR);
|
||||||
|
assert(s->stmtReturn.val->exprVar.thing->data.var.color == COLOR_EAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("ret\n");
|
||||||
|
|
||||||
|
} else abort();
|
||||||
|
|
||||||
s = s->statement.next;
|
s = s->statement.next;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ char *TOKEN_NAMES[] = {
|
|||||||
"'!='",
|
"'!='",
|
||||||
"'!'",
|
"'!'",
|
||||||
"'continue'",
|
"'continue'",
|
||||||
|
"'return'",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int isAlpha(int c) {
|
static int isAlpha(int c) {
|
||||||
@ -243,6 +244,10 @@ Token nct_tokenize(FILE *f) {
|
|||||||
free(content);
|
free(content);
|
||||||
tok.type = TOKEN_CONTINUE;
|
tok.type = TOKEN_CONTINUE;
|
||||||
return tok;
|
return tok;
|
||||||
|
} else if(!strcmp(content, "return")) {
|
||||||
|
free(content);
|
||||||
|
tok.type = TOKEN_RETURN;
|
||||||
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
tok.type = TOKEN_IDENTIFIER;
|
tok.type = TOKEN_IDENTIFIER;
|
||||||
|
@ -38,6 +38,7 @@ typedef enum {
|
|||||||
TOKEN_EXCLAMATION_EQUALS,
|
TOKEN_EXCLAMATION_EQUALS,
|
||||||
TOKEN_EXCLAMATION,
|
TOKEN_EXCLAMATION,
|
||||||
TOKEN_CONTINUE,
|
TOKEN_CONTINUE,
|
||||||
|
TOKEN_RETURN
|
||||||
} TokenKind;
|
} TokenKind;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
43
src/parse.c
43
src/parse.c
@ -652,7 +652,8 @@ static AST *parse_declaration(Parser *P) {
|
|||||||
|
|
||||||
Type *type = nct_parse_typename(P);
|
Type *type = nct_parse_typename(P);
|
||||||
|
|
||||||
if(!type) goto backtrack;
|
if(!type && (peek(P, 0).type != TOKEN_IDENTIFIER || peek(P, 1).type != TOKEN_COLON)) goto backtrack;
|
||||||
|
|
||||||
if(peek(P, 0).type != TOKEN_IDENTIFIER) goto backtrack;
|
if(peek(P, 0).type != TOKEN_IDENTIFIER) goto backtrack;
|
||||||
|
|
||||||
Token name = expect(P, TOKEN_IDENTIFIER);
|
Token name = expect(P, TOKEN_IDENTIFIER);
|
||||||
@ -708,7 +709,13 @@ static AST *parse_declaration(Parser *P) {
|
|||||||
entry->data.symbol.isExternal = isExternal;
|
entry->data.symbol.isExternal = isExternal;
|
||||||
entry->data.symbol.name = name.content;
|
entry->data.symbol.name = name.content;
|
||||||
|
|
||||||
decl->expression = nct_cast_expr(nct_parse_expression(P, 0), type);
|
decl->expression = nct_parse_expression(P, 0);
|
||||||
|
|
||||||
|
if(type) {
|
||||||
|
decl->expression = nct_cast_expr(decl->expression, type);
|
||||||
|
} else {
|
||||||
|
entry->type = decl->expression->expression.type;
|
||||||
|
}
|
||||||
|
|
||||||
if(decl->expression) {
|
if(decl->expression) {
|
||||||
//if(ret->expression->expression.constantType == EXPRESSION_NOT_CONSTANT) {
|
//if(ret->expression->expression.constantType == EXPRESSION_NOT_CONSTANT) {
|
||||||
@ -810,6 +817,38 @@ void nct_parse_statement(Parser *P) {
|
|||||||
|
|
||||||
pushstat(P, ret);
|
pushstat(P, ret);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if(maybe(P, TOKEN_RETURN)) {
|
||||||
|
ASTStmtReturn *ret = malloc(sizeof(*ret));
|
||||||
|
ret->nodeKind = AST_STMT_RETURN;
|
||||||
|
ret->next = NULL;
|
||||||
|
|
||||||
|
if(!maybe(P, TOKEN_SEMICOLON)) {
|
||||||
|
AST *expr = nct_parse_expression(P, 0);
|
||||||
|
|
||||||
|
VarTableEntry *tempo = calloc(1, sizeof(*tempo));
|
||||||
|
tempo->kind = VARTABLEENTRY_VAR;
|
||||||
|
tempo->type = expr->expression.type;
|
||||||
|
tempo->data.var.name = "$temp";
|
||||||
|
tempo->data.var.color = COLOR_EAX;
|
||||||
|
|
||||||
|
P->topLevel->vars = realloc(P->topLevel->vars, sizeof(*P->topLevel->vars) * (++P->topLevel->varCount));
|
||||||
|
P->topLevel->vars[P->topLevel->varCount - 1] = tempo;
|
||||||
|
|
||||||
|
ASTStmtAssign *assign = malloc(sizeof(*assign));
|
||||||
|
assign->nodeKind = AST_STMT_ASSIGN;
|
||||||
|
assign->what = exprvar(P, tempo);
|
||||||
|
assign->to = expr;
|
||||||
|
|
||||||
|
ret->val = exprvar(P, tempo);
|
||||||
|
|
||||||
|
pushstat(P, assign);
|
||||||
|
|
||||||
|
expect(P, TOKEN_SEMICOLON);
|
||||||
|
}
|
||||||
|
|
||||||
|
pushstat(P, ret);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else if(peek(P, 0).type == TOKEN_IDENTIFIER) {
|
} else if(peek(P, 0).type == TOKEN_IDENTIFIER) {
|
||||||
if(!strcmp(peek(P, 0).content, "@align")) {
|
if(!strcmp(peek(P, 0).content, "@align")) {
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
/* Oh and arguments aren't supported yet either */
|
/* Oh and arguments aren't supported yet either */
|
||||||
/* But functions work :) */
|
/* But functions work :) */
|
||||||
|
|
||||||
u0() foo: u0() {
|
foo: u0() {
|
||||||
u8 a = 5;
|
return 15;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user