mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-17 11:22:22 -07:00
Block Expressions and give
This commit is contained in:
+68
-3
@@ -144,6 +144,15 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
||||
bool triple_indexed; \
|
||||
}) \
|
||||
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
||||
AST_NODE_KIND(BlockExpr, "block expr", struct { \
|
||||
AstNodeArray stmts; \
|
||||
Token open, close; \
|
||||
AstNode *give_node; \
|
||||
}) \
|
||||
AST_NODE_KIND(GiveExpr, "give expression", struct { \
|
||||
Token token; \
|
||||
AstNodeArray results; \
|
||||
}) \
|
||||
AST_NODE_KIND(_ExprEnd, "", i32) \
|
||||
AST_NODE_KIND(_StmtBegin, "", i32) \
|
||||
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
|
||||
@@ -432,6 +441,10 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->DerefExpr.op;
|
||||
case AstNode_DemaybeExpr:
|
||||
return node->DemaybeExpr.op;
|
||||
case AstNode_BlockExpr:
|
||||
return node->BlockExpr.open;
|
||||
case AstNode_GiveExpr:
|
||||
return node->GiveExpr.token;
|
||||
case AstNode_BadStmt:
|
||||
return node->BadStmt.begin;
|
||||
case AstNode_EmptyStmt:
|
||||
@@ -729,6 +742,24 @@ AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *make_block_expr(AstFile *f, AstNodeArray stmts, Token open, Token close) {
|
||||
AstNode *result = make_node(f, AstNode_BlockExpr);
|
||||
result->BlockExpr.stmts = stmts;
|
||||
result->BlockExpr.open = open;
|
||||
result->BlockExpr.close = close;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_give_expr(AstFile *f, Token token, AstNodeArray results) {
|
||||
AstNode *result = make_node(f, AstNode_GiveExpr);
|
||||
result->GiveExpr.token = token;
|
||||
result->GiveExpr.results = results;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AstNode *make_bad_stmt(AstFile *f, Token begin, Token end) {
|
||||
AstNode *result = make_node(f, AstNode_BadStmt);
|
||||
result->BadStmt.begin = begin;
|
||||
@@ -1508,6 +1539,9 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
|
||||
}
|
||||
}
|
||||
|
||||
AstNodeArray parse_lhs_expr_list(AstFile *f);
|
||||
AstNodeArray parse_rhs_expr_list(AstFile *f);
|
||||
|
||||
AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
AstNode *operand = NULL; // Operand
|
||||
switch (f->curr_token.kind) {
|
||||
@@ -1623,6 +1657,17 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
return type;
|
||||
}
|
||||
|
||||
case Token_OpenBrace: {
|
||||
AstNodeArray stmts = {0};
|
||||
Token open, close;
|
||||
open = expect_token(f, Token_OpenBrace);
|
||||
f->expr_level++;
|
||||
stmts = parse_stmt_list(f);
|
||||
f->expr_level--;
|
||||
close = expect_token(f, Token_CloseBrace);
|
||||
return make_block_expr(f, stmts, open, close);
|
||||
}
|
||||
|
||||
default: {
|
||||
AstNode *type = parse_identifier_or_type(f);
|
||||
if (type != NULL) {
|
||||
@@ -2619,12 +2664,15 @@ AstNode *parse_return_stmt(AstFile *f) {
|
||||
syntax_error(f->curr_token, "You cannot use a return statement in the file scope");
|
||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
if (f->expr_level > 0) {
|
||||
syntax_error(f->curr_token, "You cannot use a return statement within an expression");
|
||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
|
||||
Token token = expect_token(f, Token_return);
|
||||
AstNodeArray results = make_ast_node_array(f);
|
||||
|
||||
if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace &&
|
||||
f->curr_token.pos.line == token.pos.line) {
|
||||
if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
|
||||
results = parse_rhs_expr_list(f);
|
||||
}
|
||||
|
||||
@@ -2632,6 +2680,23 @@ AstNode *parse_return_stmt(AstFile *f) {
|
||||
return make_return_stmt(f, token, results);
|
||||
}
|
||||
|
||||
|
||||
AstNode *parse_give_stmt(AstFile *f) {
|
||||
if (f->curr_proc == NULL) {
|
||||
syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
|
||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
if (f->expr_level == 0) {
|
||||
syntax_error(f->curr_token, "A give statement must be used within an expression");
|
||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
|
||||
Token token = expect_token(f, Token_give);
|
||||
AstNodeArray results = parse_rhs_expr_list(f);
|
||||
expect_semicolon(f, results.e[0]);
|
||||
return make_expr_stmt(f, make_give_expr(f, token, results));
|
||||
}
|
||||
|
||||
AstNode *parse_for_stmt(AstFile *f) {
|
||||
if (f->curr_proc == NULL) {
|
||||
syntax_error(f->curr_token, "You cannot use a for statement in the file scope");
|
||||
@@ -2861,7 +2926,6 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
// TODO(bill): other keywords
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
case Token_when: return parse_when_stmt(f);
|
||||
case Token_for: return parse_for_stmt(f);
|
||||
@@ -2869,6 +2933,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_defer: return parse_defer_stmt(f);
|
||||
case Token_asm: return parse_asm_stmt(f);
|
||||
case Token_return: return parse_return_stmt(f);
|
||||
case Token_give: return parse_give_stmt(f);
|
||||
|
||||
case Token_break:
|
||||
case Token_continue:
|
||||
|
||||
Reference in New Issue
Block a user