mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-14 07:01:25 -07:00
Nearly finished Jai-like declarations
This commit is contained in:
+81
-56
@@ -281,15 +281,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
AstNodeArray values; \
|
||||
u64 tags; \
|
||||
}) \
|
||||
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
AstNode *body; \
|
||||
u64 tags; \
|
||||
String foreign_name; \
|
||||
String link_name; \
|
||||
AstNode *note; \
|
||||
}) \
|
||||
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
||||
Token token, filepath; \
|
||||
String base_dir; \
|
||||
@@ -303,6 +294,10 @@ AST_NODE_KIND(_DeclEnd, "", i32) \
|
||||
bool is_using; \
|
||||
}) \
|
||||
AST_NODE_KIND(_TypeBegin, "", i32) \
|
||||
AST_NODE_KIND(HelperType, "type", struct { \
|
||||
Token token; \
|
||||
AstNode *type; \
|
||||
}) \
|
||||
AST_NODE_KIND(ProcType, "procedure type", struct { \
|
||||
Token token; \
|
||||
AstNodeArray params; \
|
||||
@@ -501,8 +496,6 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->GenericDecl.token;
|
||||
case AstNode_ValueDecl:
|
||||
return ast_node_token(node->ValueDecl.names.e[0]);
|
||||
case AstNode_ProcDecl:
|
||||
return ast_node_token(node->ProcDecl.name);
|
||||
|
||||
case AstNode_ForeignLibrary:
|
||||
return node->ForeignLibrary.token;
|
||||
@@ -519,6 +512,10 @@ Token ast_node_token(AstNode *node) {
|
||||
return ast_node_token(node->Field.type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case AstNode_HelperType:
|
||||
return node->HelperType.token;
|
||||
case AstNode_ProcType:
|
||||
return node->ProcType.token;
|
||||
case AstNode_PointerType:
|
||||
@@ -969,6 +966,15 @@ AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *make_helper_type(AstFile *f, Token token, AstNode *type) {
|
||||
AstNode *result = make_node(f, AstNode_HelperType);
|
||||
result->HelperType.token = token;
|
||||
result->HelperType.type = type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results, u64 tags, ProcCallingConvention calling_convention) {
|
||||
AstNode *result = make_node(f, AstNode_ProcType);
|
||||
result->ProcType.token = token;
|
||||
@@ -979,17 +985,6 @@ AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArr
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
|
||||
AstNode *result = make_node(f, AstNode_ProcDecl);
|
||||
result->ProcDecl.name = name;
|
||||
result->ProcDecl.type = proc_type;
|
||||
result->ProcDecl.body = body;
|
||||
result->ProcDecl.tags = tags;
|
||||
result->ProcDecl.foreign_name = foreign_name;
|
||||
result->ProcDecl.link_name = link_name;
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) {
|
||||
AstNode *result = make_node(f, AstNode_PointerType);
|
||||
result->PointerType.token = token;
|
||||
@@ -1264,6 +1259,52 @@ Token expect_closing(AstFile *f, TokenKind kind, String context) {
|
||||
return expect_token(f, kind);
|
||||
}
|
||||
|
||||
bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
if (s == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (s->kind) {
|
||||
case AstNode_HelperType:
|
||||
return is_semicolon_optional_for_node(f, s->HelperType.type);
|
||||
|
||||
case AstNode_StructType:
|
||||
case AstNode_UnionType:
|
||||
case AstNode_RawUnionType:
|
||||
case AstNode_EnumType:
|
||||
return true;
|
||||
case AstNode_ProcLit:
|
||||
return true;
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
if (!s->ValueDecl.is_var) {
|
||||
if (s->ValueDecl.values.count > 0) {
|
||||
AstNode *last = s->ValueDecl.values.e[s->ValueDecl.values.count-1];
|
||||
return is_semicolon_optional_for_node(f, last);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AstNode_GenericDecl:
|
||||
if (s->GenericDecl.close.kind == Token_CloseBrace) {
|
||||
return true;
|
||||
} else if (s->GenericDecl.token.kind == Token_type) {
|
||||
if (f->prev_token.kind == Token_CloseBrace) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AstNode_TypeSpec:
|
||||
if (f->prev_token.kind == Token_CloseBrace) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void expect_semicolon(AstFile *f, AstNode *s) {
|
||||
if (allow_token(f, Token_Semicolon)) {
|
||||
return;
|
||||
@@ -1277,24 +1318,8 @@ void expect_semicolon(AstFile *f, AstNode *s) {
|
||||
|
||||
if (s != NULL) {
|
||||
if (prev_token.pos.line != f->curr_token.pos.line) {
|
||||
switch (s->kind) {
|
||||
case AstNode_ProcDecl:
|
||||
if (is_semicolon_optional_for_node(f, s)) {
|
||||
return;
|
||||
case AstNode_GenericDecl:
|
||||
if (s->GenericDecl.close.kind == Token_CloseBrace) {
|
||||
return;
|
||||
} else if (s->GenericDecl.token.kind == Token_type) {
|
||||
if (f->prev_token.kind == Token_CloseBrace) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AstNode_TypeSpec:
|
||||
if (f->prev_token.kind == Token_CloseBrace) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (s->kind) {
|
||||
@@ -1319,7 +1344,6 @@ AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_nam
|
||||
AstNodeArray parse_stmt_list(AstFile *f);
|
||||
AstNode * parse_stmt(AstFile *f);
|
||||
AstNode * parse_body(AstFile *f);
|
||||
AstNode * parse_proc_decl(AstFile *f);
|
||||
void parse_proc_signature(AstFile *f, AstNodeArray *params, AstNodeArray *results);
|
||||
|
||||
|
||||
@@ -1571,6 +1595,7 @@ 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_simple_stmt (AstFile *f);
|
||||
AstNode * parse_type (AstFile *f);
|
||||
|
||||
AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
|
||||
if (statement == NULL) {
|
||||
@@ -1745,10 +1770,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
String foreign_name = {0};
|
||||
String link_name = {0};
|
||||
AstNode *type = parse_proc_type(f, &foreign_name, &link_name);
|
||||
u64 tags = type->ProcType.tags;
|
||||
|
||||
if (f->curr_token.kind == Token_OpenBrace) {
|
||||
u64 tags = type->ProcType.tags;
|
||||
|
||||
if ((tags & ProcTag_foreign) != 0) {
|
||||
syntax_error(token, "A procedure tagged as `#foreign` cannot have a body");
|
||||
}
|
||||
@@ -1760,6 +1784,13 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
return make_proc_lit(f, type, body, tags, foreign_name, link_name);
|
||||
}
|
||||
|
||||
if ((tags & ProcTag_foreign) != 0) {
|
||||
return make_proc_lit(f, type, NULL, tags, foreign_name, link_name);
|
||||
}
|
||||
if ((tags & ProcTag_link_name) != 0) {
|
||||
syntax_error(token, "A procedure typed cannot be tagged with `#link_name`");
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -1932,7 +1963,6 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
AstNode *parse_type(AstFile *f);
|
||||
|
||||
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
|
||||
switch (f->curr_token.kind) {
|
||||
@@ -2240,17 +2270,6 @@ PARSE_SPEC_PROC(parse_include_spec) {
|
||||
|
||||
AstNode *parse_decl(AstFile *f) {
|
||||
switch (f->curr_token.kind) {
|
||||
// case Token_var:
|
||||
// case Token_const:
|
||||
// return parse_generic_decl(f, f->curr_token.kind, parse_value_spec);
|
||||
|
||||
case Token_type:
|
||||
return parse_generic_decl(f, f->curr_token.kind, parse_type_spec);
|
||||
|
||||
case Token_proc:
|
||||
// TODO(bill): Should I allow procedures to use the generic declaration syntax?
|
||||
return parse_proc_decl(f);
|
||||
|
||||
case Token_import:
|
||||
return parse_generic_decl(f, f->curr_token.kind, parse_import_spec);
|
||||
case Token_include:
|
||||
@@ -2504,6 +2523,12 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
return e;
|
||||
}
|
||||
|
||||
case Token_type: {
|
||||
Token token = expect_token(f, Token_type);
|
||||
AstNode *type = parse_type(f);
|
||||
return make_helper_type(f, token, type);
|
||||
}
|
||||
|
||||
case Token_Pointer: {
|
||||
Token token = expect_token(f, Token_Pointer);
|
||||
AstNode *elem = parse_type(f);
|
||||
@@ -2681,7 +2706,7 @@ AstNode *parse_body(AstFile *f) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
AstNode *parse_proc_decl(AstFile *f) {
|
||||
if (look_ahead_token_kind(f, 1) == Token_OpenParen) {
|
||||
// NOTE(bill): It's an anonymous procedure
|
||||
@@ -2720,7 +2745,7 @@ AstNode *parse_proc_decl(AstFile *f) {
|
||||
}
|
||||
|
||||
return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
|
||||
}
|
||||
} */
|
||||
|
||||
AstNode *parse_if_stmt(AstFile *f) {
|
||||
if (f->curr_proc == NULL) {
|
||||
|
||||
Reference in New Issue
Block a user