|
@@ -302,16 +302,20 @@ AST_NODE_KIND(_DeclEnd, "", i32) \
|
|
AstNode * type; \
|
|
AstNode * type; \
|
|
u32 flags; \
|
|
u32 flags; \
|
|
}) \
|
|
}) \
|
|
|
|
+ AST_NODE_KIND(FieldList, "field list", struct { \
|
|
|
|
+ Token token; \
|
|
|
|
+ AstNodeArray list; \
|
|
|
|
+ }) \
|
|
AST_NODE_KIND(_TypeBegin, "", i32) \
|
|
AST_NODE_KIND(_TypeBegin, "", i32) \
|
|
AST_NODE_KIND(HelperType, "type", struct { \
|
|
AST_NODE_KIND(HelperType, "type", struct { \
|
|
Token token; \
|
|
Token token; \
|
|
AstNode *type; \
|
|
AstNode *type; \
|
|
}) \
|
|
}) \
|
|
AST_NODE_KIND(ProcType, "procedure type", struct { \
|
|
AST_NODE_KIND(ProcType, "procedure type", struct { \
|
|
- Token token; \
|
|
|
|
- AstNodeArray params; \
|
|
|
|
- AstNodeArray results; \
|
|
|
|
- u64 tags; \
|
|
|
|
|
|
+ Token token; \
|
|
|
|
+ AstNode *params; \
|
|
|
|
+ AstNode *results; \
|
|
|
|
+ u64 tags; \
|
|
ProcCallingConvention calling_convention; \
|
|
ProcCallingConvention calling_convention; \
|
|
}) \
|
|
}) \
|
|
AST_NODE_KIND(PointerType, "pointer type", struct { \
|
|
AST_NODE_KIND(PointerType, "pointer type", struct { \
|
|
@@ -478,11 +482,14 @@ Token ast_node_token(AstNode *node) {
|
|
case AstNode_ImportDecl: return node->ImportDecl.token;
|
|
case AstNode_ImportDecl: return node->ImportDecl.token;
|
|
case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
|
|
case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
|
|
|
|
|
|
|
|
+
|
|
case AstNode_Field:
|
|
case AstNode_Field:
|
|
if (node->Field.names.count > 0) {
|
|
if (node->Field.names.count > 0) {
|
|
return ast_node_token(node->Field.names.e[0]);
|
|
return ast_node_token(node->Field.names.e[0]);
|
|
}
|
|
}
|
|
return ast_node_token(node->Field.type);
|
|
return ast_node_token(node->Field.type);
|
|
|
|
+ case AstNode_FieldList:
|
|
|
|
+ return node->FieldList.token;
|
|
|
|
|
|
case AstNode_HelperType: return node->HelperType.token;
|
|
case AstNode_HelperType: return node->HelperType.token;
|
|
case AstNode_ProcType: return node->ProcType.token;
|
|
case AstNode_ProcType: return node->ProcType.token;
|
|
@@ -952,6 +959,13 @@ AstNode *ast_field(AstFile *f, AstNodeArray names, AstNode *type, u32 flags) {
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+AstNode *ast_field_list(AstFile *f, Token token, AstNodeArray list) {
|
|
|
|
+ AstNode *result = make_ast_node(f, AstNode_FieldList);
|
|
|
|
+ result->FieldList.token = token;
|
|
|
|
+ result->FieldList.list = list;
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
|
|
AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
|
|
AstNode *result = make_ast_node(f, AstNode_HelperType);
|
|
AstNode *result = make_ast_node(f, AstNode_HelperType);
|
|
@@ -961,7 +975,7 @@ AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-AstNode *ast_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) {
|
|
|
|
|
|
+AstNode *ast_proc_type(AstFile *f, Token token, AstNode *params, AstNode *results, u64 tags, ProcCallingConvention calling_convention) {
|
|
AstNode *result = make_ast_node(f, AstNode_ProcType);
|
|
AstNode *result = make_ast_node(f, AstNode_ProcType);
|
|
result->ProcType.token = token;
|
|
result->ProcType.token = token;
|
|
result->ProcType.params = params;
|
|
result->ProcType.params = params;
|
|
@@ -1308,7 +1322,6 @@ AstNode * parse_proc_type(AstFile *f, AstNode **foreign_library, String *fore
|
|
AstNodeArray parse_stmt_list(AstFile *f);
|
|
AstNodeArray parse_stmt_list(AstFile *f);
|
|
AstNode * parse_stmt(AstFile *f);
|
|
AstNode * parse_stmt(AstFile *f);
|
|
AstNode * parse_body(AstFile *f);
|
|
AstNode * parse_body(AstFile *f);
|
|
-void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -2258,15 +2271,39 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
|
|
return parse_body(f);
|
|
return parse_body(f);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow);
|
|
|
|
+
|
|
|
|
|
|
|
|
+AstNode *parse_results(AstFile *f) {
|
|
|
|
+ if (!allow_token(f, Token_ArrowRight)) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ if (f->curr_token.kind != Token_OpenParen) {
|
|
|
|
+ Token begin_token = f->curr_token;
|
|
|
|
+ AstNodeArray empty_names = {0};
|
|
|
|
+ AstNodeArray list = make_ast_node_array(f);
|
|
|
|
+ AstNode *type = parse_type(f);
|
|
|
|
+ array_add(&list, ast_field(f, empty_names, type, 0));
|
|
|
|
+ return ast_field_list(f, begin_token, list);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ AstNode *list = NULL;
|
|
|
|
+ expect_token(f, Token_OpenParen);
|
|
|
|
+ list = parse_field_list(f, NULL, 0, Token_Comma, Token_CloseParen);
|
|
|
|
+ expect_token_after(f, Token_CloseParen, "parameter list");
|
|
|
|
+ return list;
|
|
|
|
+}
|
|
|
|
|
|
AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
|
|
AstNode *parse_proc_type(AstFile *f, AstNode **foreign_library_, String *foreign_name_, String *link_name_) {
|
|
- AstNodeArray params = {0};
|
|
|
|
- AstNodeArray results = {0};
|
|
|
|
|
|
+ AstNode *params = {0};
|
|
|
|
+ AstNode *results = {0};
|
|
|
|
|
|
Token proc_token = expect_token(f, Token_proc);
|
|
Token proc_token = expect_token(f, Token_proc);
|
|
- parse_proc_signature(f, ¶ms, &results);
|
|
|
|
|
|
+ expect_token(f, Token_OpenParen);
|
|
|
|
+ params = parse_field_list(f, NULL, FieldFlag_Signature, Token_Comma, Token_CloseParen);
|
|
|
|
+ expect_token_after(f, Token_CloseParen, "parameter list");
|
|
|
|
+ results = parse_results(f);
|
|
|
|
|
|
u64 tags = 0;
|
|
u64 tags = 0;
|
|
String foreign_name = {0};
|
|
String foreign_name = {0};
|
|
@@ -2404,8 +2441,9 @@ AstNodeArray convert_to_ident_list(AstFile *f, AstNodeAndFlagsArray list, bool i
|
|
return idents;
|
|
return idents;
|
|
}
|
|
}
|
|
|
|
|
|
-AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
|
|
|
|
- TokenKind separator, TokenKind follow) {
|
|
|
|
|
|
+AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind separator, TokenKind follow) {
|
|
|
|
+ Token start_token = f->curr_token;
|
|
|
|
+
|
|
AstNodeArray params = make_ast_node_array(f);
|
|
AstNodeArray params = make_ast_node_array(f);
|
|
AstNodeAndFlagsArray list = {0}; array_init(&list, heap_allocator()); // LEAK(bill):
|
|
AstNodeAndFlagsArray list = {0}; array_init(&list, heap_allocator()); // LEAK(bill):
|
|
isize total_name_count = 0;
|
|
isize total_name_count = 0;
|
|
@@ -2465,7 +2503,7 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
|
|
}
|
|
}
|
|
|
|
|
|
if (name_count_) *name_count_ = total_name_count;
|
|
if (name_count_) *name_count_ = total_name_count;
|
|
- return params;
|
|
|
|
|
|
+ return ast_field_list(f, start_token, params);
|
|
}
|
|
}
|
|
|
|
|
|
for_array(i, list) {
|
|
for_array(i, list) {
|
|
@@ -2483,11 +2521,11 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags,
|
|
}
|
|
}
|
|
|
|
|
|
if (name_count_) *name_count_ = total_name_count;
|
|
if (name_count_) *name_count_ = total_name_count;
|
|
- return params;
|
|
|
|
|
|
+ return ast_field_list(f, start_token, params);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
|
|
|
|
|
|
+AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
|
|
return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace);
|
|
return parse_field_list(f, field_count_, flags, Token_Comma, Token_CloseBrace);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2617,9 +2655,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|
|
|
|
|
Token open = expect_token_after(f, Token_OpenBrace, "struct");
|
|
Token open = expect_token_after(f, Token_OpenBrace, "struct");
|
|
isize decl_count = 0;
|
|
isize decl_count = 0;
|
|
- AstNodeArray decls = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct"));
|
|
|
|
|
|
+ AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("struct"));
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
|
|
|
|
|
|
+ AstNodeArray decls = {0};
|
|
|
|
+ if (fields != NULL) {
|
|
|
|
+ GB_ASSERT(fields->kind == AstNode_FieldList);
|
|
|
|
+ decls = fields->FieldList.list;
|
|
|
|
+ }
|
|
|
|
+
|
|
return ast_struct_type(f, token, decls, decl_count, is_packed, is_ordered, align);
|
|
return ast_struct_type(f, token, decls, decl_count, is_packed, is_ordered, align);
|
|
} break;
|
|
} break;
|
|
|
|
|
|
@@ -2627,9 +2671,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|
Token token = expect_token(f, Token_union);
|
|
Token token = expect_token(f, Token_union);
|
|
Token open = expect_token_after(f, Token_OpenBrace, "union");
|
|
Token open = expect_token_after(f, Token_OpenBrace, "union");
|
|
isize decl_count = 0;
|
|
isize decl_count = 0;
|
|
- AstNodeArray decls = parse_record_fields(f, &decl_count, 0, str_lit("union"));
|
|
|
|
|
|
+ AstNode *fields = parse_record_fields(f, &decl_count, 0, str_lit("union"));
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
|
|
|
|
|
|
+ AstNodeArray decls = {0};
|
|
|
|
+ if (fields != NULL) {
|
|
|
|
+ GB_ASSERT(fields->kind == AstNode_FieldList);
|
|
|
|
+ decls = fields->FieldList.list;
|
|
|
|
+ }
|
|
|
|
+
|
|
return ast_union_type(f, token, decls, decl_count);
|
|
return ast_union_type(f, token, decls, decl_count);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2637,9 +2687,15 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|
Token token = expect_token(f, Token_raw_union);
|
|
Token token = expect_token(f, Token_raw_union);
|
|
Token open = expect_token_after(f, Token_OpenBrace, "raw_union");
|
|
Token open = expect_token_after(f, Token_OpenBrace, "raw_union");
|
|
isize decl_count = 0;
|
|
isize decl_count = 0;
|
|
- AstNodeArray decls = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("raw_union"));
|
|
|
|
|
|
+ AstNode *fields = parse_record_fields(f, &decl_count, FieldFlag_using, str_lit("raw_union"));
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
Token close = expect_token(f, Token_CloseBrace);
|
|
|
|
|
|
|
|
+ AstNodeArray decls = {0};
|
|
|
|
+ if (fields != NULL) {
|
|
|
|
+ GB_ASSERT(fields->kind == AstNode_FieldList);
|
|
|
|
+ decls = fields->FieldList.list;
|
|
|
|
+ }
|
|
|
|
+
|
|
return ast_raw_union_type(f, token, decls, decl_count);
|
|
return ast_raw_union_type(f, token, decls, decl_count);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2679,39 +2735,6 @@ AstNode *parse_type_or_ident(AstFile *f) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-AstNodeArray parse_results(AstFile *f) {
|
|
|
|
- AstNodeArray results = make_ast_node_array(f);
|
|
|
|
- if (allow_token(f, Token_ArrowRight)) {
|
|
|
|
- if (f->curr_token.kind == Token_OpenParen) {
|
|
|
|
- expect_token(f, Token_OpenParen);
|
|
|
|
- while (f->curr_token.kind != Token_CloseParen &&
|
|
|
|
- f->curr_token.kind != Token_EOF) {
|
|
|
|
- array_add(&results, parse_type(f));
|
|
|
|
- if (f->curr_token.kind != Token_Comma) {
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- next_token(f);
|
|
|
|
- }
|
|
|
|
- expect_token(f, Token_CloseParen);
|
|
|
|
-
|
|
|
|
- return results;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- array_add(&results, parse_type(f));
|
|
|
|
- return results;
|
|
|
|
- }
|
|
|
|
- return results;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void parse_proc_signature(AstFile *f,
|
|
|
|
- AstNodeArray *params,
|
|
|
|
- AstNodeArray *results) {
|
|
|
|
- expect_token(f, Token_OpenParen);
|
|
|
|
- *params = parse_field_list(f, NULL, FieldFlag_Signature, Token_Comma, Token_CloseParen);
|
|
|
|
- expect_token_after(f, Token_CloseParen, "parameter list");
|
|
|
|
- *results = parse_results(f);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
AstNode *parse_body(AstFile *f) {
|
|
AstNode *parse_body(AstFile *f) {
|
|
AstNodeArray stmts = {0};
|
|
AstNodeArray stmts = {0};
|
|
Token open, close;
|
|
Token open, close;
|
|
@@ -2727,48 +2750,6 @@ AstNode *parse_body(AstFile *f) {
|
|
return ast_block_stmt(f, stmts, open, close);
|
|
return ast_block_stmt(f, stmts, open, close);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
-AstNode *parse_proc_decl(AstFile *f) {
|
|
|
|
- if (look_ahead_token_kind(f, 1) == Token_OpenParen) {
|
|
|
|
- // NOTE(bill): It's an anonymous procedure
|
|
|
|
- // NOTE(bill): This look-ahead technically makes the grammar LALR(2)
|
|
|
|
- // but is that a problem in practice?
|
|
|
|
- return ast_expr_stmt(f, parse_expr(f, true));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- AstNodeArray params = {0};
|
|
|
|
- AstNodeArray results = {0};
|
|
|
|
-
|
|
|
|
- Token proc_token = expect_token(f, Token_proc);
|
|
|
|
- AstNode *name = parse_ident(f);
|
|
|
|
- parse_proc_signature(f, ¶ms, &results);
|
|
|
|
-
|
|
|
|
- u64 tags = 0;
|
|
|
|
- String foreign_name = {0};
|
|
|
|
- String link_name = {0};
|
|
|
|
- ProcCallingConvention cc = ProcCC_Odin;
|
|
|
|
-
|
|
|
|
- parse_proc_tags(f, &tags, &foreign_name, &link_name, &cc);
|
|
|
|
-
|
|
|
|
- AstNode *proc_type = ast_proc_type(f, proc_token, params, results, tags, cc);
|
|
|
|
- AstNode *body = NULL;
|
|
|
|
-
|
|
|
|
- if (f->curr_token.kind == Token_OpenBrace) {
|
|
|
|
- if ((tags & ProcTag_foreign) != 0) {
|
|
|
|
- syntax_error(proc_token, "A procedure tagged as `#foreign` cannot have a body");
|
|
|
|
- }
|
|
|
|
- AstNode *curr_proc = f->curr_proc;
|
|
|
|
- f->curr_proc = proc_type;
|
|
|
|
- body = parse_body(f);
|
|
|
|
- f->curr_proc = curr_proc;
|
|
|
|
- } else if ((tags & ProcTag_foreign) == 0) {
|
|
|
|
- syntax_error(proc_token, "Only a procedure tagged as `#foreign` cannot have a body");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return ast_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
|
|
|
|
-} */
|
|
|
|
-
|
|
|
|
AstNode *parse_if_stmt(AstFile *f) {
|
|
AstNode *parse_if_stmt(AstFile *f) {
|
|
if (f->curr_proc == NULL) {
|
|
if (f->curr_proc == NULL) {
|
|
syntax_error(f->curr_token, "You cannot use an if statement in the file scope");
|
|
syntax_error(f->curr_token, "You cannot use an if statement in the file scope");
|