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_DECL) {
|
||||
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 {
|
||||
abort();
|
||||
}
|
||||
@ -447,6 +451,32 @@ static char *ast_dumpe(AST *e) {
|
||||
return r;
|
||||
} else if(e->nodeKind == AST_EXPR_STACK_POINTER) {
|
||||
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]);
|
||||
@ -495,6 +525,15 @@ static char *ast_dumps(AST *s) {
|
||||
}
|
||||
|
||||
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]);
|
||||
|
10
src/ast.h
10
src/ast.h
@ -44,7 +44,8 @@
|
||||
K(AST_EXPR_ARRAY) \
|
||||
K(AST_EXPR_FUNC) \
|
||||
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;
|
||||
extern const char *AST_KIND_STR[];
|
||||
@ -256,6 +257,12 @@ typedef struct {
|
||||
Token name;
|
||||
} ASTStmtExtSection;
|
||||
|
||||
typedef struct {
|
||||
ASTStmt;
|
||||
|
||||
union AST *val;
|
||||
} ASTStmtReturn;
|
||||
|
||||
typedef union AST {
|
||||
ASTKind nodeKind;
|
||||
|
||||
@ -268,6 +275,7 @@ typedef union AST {
|
||||
ASTStmtContinue stmtContinue;
|
||||
ASTStmtExpr stmtExpr;
|
||||
ASTStmtAssign stmtAssign;
|
||||
ASTStmtReturn stmtReturn;
|
||||
ASTExpr expression;
|
||||
ASTExprPrimitive exprPrim;
|
||||
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);
|
||||
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ char *TOKEN_NAMES[] = {
|
||||
"'!='",
|
||||
"'!'",
|
||||
"'continue'",
|
||||
"'return'",
|
||||
};
|
||||
|
||||
static int isAlpha(int c) {
|
||||
@ -243,6 +244,10 @@ Token nct_tokenize(FILE *f) {
|
||||
free(content);
|
||||
tok.type = TOKEN_CONTINUE;
|
||||
return tok;
|
||||
} else if(!strcmp(content, "return")) {
|
||||
free(content);
|
||||
tok.type = TOKEN_RETURN;
|
||||
return tok;
|
||||
}
|
||||
|
||||
tok.type = TOKEN_IDENTIFIER;
|
||||
|
@ -38,6 +38,7 @@ typedef enum {
|
||||
TOKEN_EXCLAMATION_EQUALS,
|
||||
TOKEN_EXCLAMATION,
|
||||
TOKEN_CONTINUE,
|
||||
TOKEN_RETURN
|
||||
} TokenKind;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
Token name = expect(P, TOKEN_IDENTIFIER);
|
||||
@ -708,7 +709,13 @@ static AST *parse_declaration(Parser *P) {
|
||||
entry->data.symbol.isExternal = isExternal;
|
||||
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(ret->expression->expression.constantType == EXPRESSION_NOT_CONSTANT) {
|
||||
@ -810,6 +817,38 @@ void nct_parse_statement(Parser *P) {
|
||||
|
||||
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;
|
||||
} else if(peek(P, 0).type == TOKEN_IDENTIFIER) {
|
||||
if(!strcmp(peek(P, 0).content, "@align")) {
|
||||
|
@ -2,6 +2,6 @@
|
||||
/* Oh and arguments aren't supported yet either */
|
||||
/* But functions work :) */
|
||||
|
||||
u0() foo: u0() {
|
||||
u8 a = 5;
|
||||
foo: u0() {
|
||||
return 15;
|
||||
};
|
||||
|
@ -19,4 +19,4 @@ loop {}
|
||||
u8[19] string: "Hello from Nectar!\0";
|
||||
|
||||
@align(510);
|
||||
u16 bootsig: 16rAA55;
|
||||
u16 bootsig: 16rAA55;
|
||||
|
Loading…
Reference in New Issue
Block a user