diff --git a/src/ast.c b/src/ast.c index 9e3fe52..0a7aa5b 100644 --- a/src/ast.c +++ b/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]); diff --git a/src/ast.h b/src/ast.h index cb5a38c..d3a76a0 100644 --- a/src/ast.h +++ b/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; diff --git a/src/cg.c b/src/cg.c index de49b41..41c2742 100644 --- a/src/cg.c +++ b/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; } diff --git a/src/lexer.c b/src/lexer.c index 3c5af57..04e8f52 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -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; diff --git a/src/lexer.h b/src/lexer.h index dae5eae..11819d3 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -38,6 +38,7 @@ typedef enum { TOKEN_EXCLAMATION_EQUALS, TOKEN_EXCLAMATION, TOKEN_CONTINUE, + TOKEN_RETURN } TokenKind; typedef struct { diff --git a/src/parse.c b/src/parse.c index 63e615b..6b397a5 100644 --- a/src/parse.c +++ b/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")) { diff --git a/tests/funcdefs.nct b/tests/funcdefs.nct index f9c4312..31facf7 100644 --- a/tests/funcdefs.nct +++ b/tests/funcdefs.nct @@ -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; }; diff --git a/tests/mbr.nct b/tests/mbr.nct index 2b06acb..65656d4 100644 --- a/tests/mbr.nct +++ b/tests/mbr.nct @@ -19,4 +19,4 @@ loop {} u8[19] string: "Hello from Nectar!\0"; @align(510); -u16 bootsig: 16rAA55; \ No newline at end of file +u16 bootsig: 16rAA55;