|
@@ -124,11 +124,12 @@ AstNodeArray make_ast_node_array(AstFile *f) {
|
|
AstNode *expr; \
|
|
AstNode *expr; \
|
|
}) \
|
|
}) \
|
|
AST_NODE_KIND(ProcLit, "procedure literal", struct { \
|
|
AST_NODE_KIND(ProcLit, "procedure literal", struct { \
|
|
- AstNode *type; \
|
|
|
|
- AstNode *body; \
|
|
|
|
- u64 tags; \
|
|
|
|
- String foreign_name; \
|
|
|
|
- String link_name; \
|
|
|
|
|
|
+ AstNode *type; \
|
|
|
|
+ AstNode *body; \
|
|
|
|
+ u64 tags; \
|
|
|
|
+ AstNode *foreign_library; \
|
|
|
|
+ String foreign_name; \
|
|
|
|
+ String link_name; \
|
|
}) \
|
|
}) \
|
|
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
|
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
|
AstNode *type; \
|
|
AstNode *type; \
|
|
@@ -302,6 +303,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
|
}) \
|
|
}) \
|
|
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
|
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
|
Token token, filepath; \
|
|
Token token, filepath; \
|
|
|
|
+ Token library_name; \
|
|
String base_dir; \
|
|
String base_dir; \
|
|
AstNode *cond; \
|
|
AstNode *cond; \
|
|
bool is_system; \
|
|
bool is_system; \
|
|
@@ -774,11 +776,12 @@ AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) {
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, String foreign_name, String link_name) {
|
|
|
|
|
|
+AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags, AstNode *foreign_library, String foreign_name, String link_name) {
|
|
AstNode *result = make_node(f, AstNode_ProcLit);
|
|
AstNode *result = make_node(f, AstNode_ProcLit);
|
|
result->ProcLit.type = type;
|
|
result->ProcLit.type = type;
|
|
result->ProcLit.body = body;
|
|
result->ProcLit.body = body;
|
|
result->ProcLit.tags = tags;
|
|
result->ProcLit.tags = tags;
|
|
|
|
+ result->ProcLit.foreign_library = foreign_library;
|
|
result->ProcLit.foreign_name = foreign_name;
|
|
result->ProcLit.foreign_name = foreign_name;
|
|
result->ProcLit.link_name = link_name;
|
|
result->ProcLit.link_name = link_name;
|
|
return result;
|
|
return result;
|
|
@@ -1112,14 +1115,6 @@ AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArra
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
-AstNode *make_foreign_library(AstFile *f, Token token, Token filepath, AstNode *cond, bool is_system) {
|
|
|
|
- AstNode *result = make_node(f, AstNode_ForeignLibrary);
|
|
|
|
- result->ForeignLibrary.token = token;
|
|
|
|
- result->ForeignLibrary.filepath = filepath;
|
|
|
|
- result->ForeignLibrary.cond = cond;
|
|
|
|
- result->ForeignLibrary.is_system = is_system;
|
|
|
|
- return result;
|
|
|
|
-}
|
|
|
|
|
|
|
|
AstNode *make_value_decl(AstFile *f, bool is_var, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
|
AstNode *make_value_decl(AstFile *f, bool is_var, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
|
AstNode *result = make_node(f, AstNode_ValueDecl);
|
|
AstNode *result = make_node(f, AstNode_ValueDecl);
|
|
@@ -1141,6 +1136,16 @@ AstNode *make_import_decl(AstFile *f, Token token, bool is_import, Token relpath
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+AstNode *make_foreign_library(AstFile *f, Token token, Token filepath, Token library_name, AstNode *cond, bool is_system) {
|
|
|
|
+ AstNode *result = make_node(f, AstNode_ForeignLibrary);
|
|
|
|
+ result->ForeignLibrary.token = token;
|
|
|
|
+ result->ForeignLibrary.filepath = filepath;
|
|
|
|
+ result->ForeignLibrary.library_name = library_name;
|
|
|
|
+ result->ForeignLibrary.cond = cond;
|
|
|
|
+ result->ForeignLibrary.is_system = is_system;
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
|
|
bool next_token(AstFile *f) {
|
|
bool next_token(AstFile *f) {
|
|
Token prev = f->curr_token;
|
|
Token prev = f->curr_token;
|
|
@@ -1316,7 +1321,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
|
case AstNode_EnumType:
|
|
case AstNode_EnumType:
|
|
return true;
|
|
return true;
|
|
case AstNode_ProcLit:
|
|
case AstNode_ProcLit:
|
|
- return true;
|
|
|
|
|
|
+ return s->ProcLit.body != NULL;
|
|
|
|
|
|
case AstNode_ValueDecl:
|
|
case AstNode_ValueDecl:
|
|
if (!s->ValueDecl.is_var) {
|
|
if (!s->ValueDecl.is_var) {
|
|
@@ -1366,7 +1371,7 @@ void expect_semicolon(AstFile *f, AstNode *s) {
|
|
|
|
|
|
|
|
|
|
AstNode * parse_expr(AstFile *f, bool lhs);
|
|
AstNode * parse_expr(AstFile *f, bool lhs);
|
|
-AstNode * parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_);
|
|
|
|
|
|
+AstNode * parse_proc_type(AstFile *f, AstNode **foreign_library, String *foreign_name, String *link_name);
|
|
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);
|
|
@@ -1508,7 +1513,7 @@ bool is_foreign_name_valid(String name) {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name, ProcCallingConvention *calling_convention) {
|
|
|
|
|
|
+void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, String *foreign_name, String *link_name, ProcCallingConvention *calling_convention) {
|
|
// TODO(bill): Add this to procedure literals too
|
|
// TODO(bill): Add this to procedure literals too
|
|
GB_ASSERT(tags != NULL);
|
|
GB_ASSERT(tags != NULL);
|
|
GB_ASSERT(link_name != NULL);
|
|
GB_ASSERT(link_name != NULL);
|
|
@@ -1528,6 +1533,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
|
|
|
|
|
|
if (str_eq(tag_name, str_lit("foreign"))) {
|
|
if (str_eq(tag_name, str_lit("foreign"))) {
|
|
check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
|
|
check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
|
|
|
|
+ *foreign_library_token = parse_identifier(f);
|
|
if (f->curr_token.kind == Token_String) {
|
|
if (f->curr_token.kind == Token_String) {
|
|
*foreign_name = f->curr_token.string;
|
|
*foreign_name = f->curr_token.string;
|
|
// TODO(bill): Check if valid string
|
|
// TODO(bill): Check if valid string
|
|
@@ -1785,9 +1791,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|
// Parse Procedure Type or Literal
|
|
// Parse Procedure Type or Literal
|
|
case Token_proc: {
|
|
case Token_proc: {
|
|
Token token = f->curr_token;
|
|
Token token = f->curr_token;
|
|
|
|
+ AstNode *foreign_library = NULL;
|
|
String foreign_name = {0};
|
|
String foreign_name = {0};
|
|
String link_name = {0};
|
|
String link_name = {0};
|
|
- AstNode *type = parse_proc_type(f, &foreign_name, &link_name);
|
|
|
|
|
|
+ AstNode *type = parse_proc_type(f, &foreign_library, &foreign_name, &link_name);
|
|
u64 tags = type->ProcType.tags;
|
|
u64 tags = type->ProcType.tags;
|
|
|
|
|
|
if (f->curr_token.kind == Token_OpenBrace) {
|
|
if (f->curr_token.kind == Token_OpenBrace) {
|
|
@@ -1800,11 +1807,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|
body = parse_body(f);
|
|
body = parse_body(f);
|
|
f->curr_proc = curr_proc;
|
|
f->curr_proc = curr_proc;
|
|
|
|
|
|
- return make_proc_lit(f, type, body, tags, foreign_name, link_name);
|
|
|
|
|
|
+ return make_proc_lit(f, type, body, tags, foreign_library, foreign_name, link_name);
|
|
}
|
|
}
|
|
|
|
|
|
if ((tags & ProcTag_foreign) != 0) {
|
|
if ((tags & ProcTag_foreign) != 0) {
|
|
- return make_proc_lit(f, type, NULL, tags, foreign_name, link_name);
|
|
|
|
|
|
+ return make_proc_lit(f, type, NULL, tags, foreign_library, foreign_name, link_name);
|
|
}
|
|
}
|
|
if (tags != 0) {
|
|
if (tags != 0) {
|
|
syntax_error(token, "A procedure type cannot have tags");
|
|
syntax_error(token, "A procedure type cannot have tags");
|
|
@@ -2312,7 +2319,7 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-AstNode *parse_proc_type(AstFile *f, 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 params = {0};
|
|
AstNodeArray results = {0};
|
|
AstNodeArray results = {0};
|
|
|
|
|
|
@@ -2322,12 +2329,14 @@ AstNode *parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_)
|
|
u64 tags = 0;
|
|
u64 tags = 0;
|
|
String foreign_name = {0};
|
|
String foreign_name = {0};
|
|
String link_name = {0};
|
|
String link_name = {0};
|
|
|
|
+ AstNode *foreign_library = NULL;
|
|
ProcCallingConvention cc = ProcCC_Odin;
|
|
ProcCallingConvention cc = ProcCC_Odin;
|
|
|
|
|
|
- parse_proc_tags(f, &tags, &foreign_name, &link_name, &cc);
|
|
|
|
|
|
+ parse_proc_tags(f, &tags, &foreign_library, &foreign_name, &link_name, &cc);
|
|
|
|
|
|
- if (foreign_name_) *foreign_name_ = foreign_name;
|
|
|
|
- if (link_name_) *link_name_ = link_name;
|
|
|
|
|
|
+ if (foreign_library_) *foreign_library_ = foreign_library;
|
|
|
|
+ if (foreign_name_) *foreign_name_ = foreign_name;
|
|
|
|
+ if (link_name_) *link_name_ = link_name;
|
|
|
|
|
|
return make_proc_type(f, proc_token, params, results, tags, cc);
|
|
return make_proc_type(f, proc_token, params, results, tags, cc);
|
|
}
|
|
}
|
|
@@ -2644,7 +2653,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
|
|
|
|
|
case Token_proc: {
|
|
case Token_proc: {
|
|
Token token = f->curr_token;
|
|
Token token = f->curr_token;
|
|
- AstNode *pt = parse_proc_type(f, NULL, NULL);
|
|
|
|
|
|
+ AstNode *pt = parse_proc_type(f, NULL, NULL, NULL);
|
|
if (pt->ProcType.tags != 0) {
|
|
if (pt->ProcType.tags != 0) {
|
|
syntax_error(token, "A procedure type cannot have tags");
|
|
syntax_error(token, "A procedure type cannot have tags");
|
|
}
|
|
}
|
|
@@ -3327,6 +3336,21 @@ AstNode *parse_stmt(AstFile *f) {
|
|
return s;
|
|
return s;
|
|
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
|
|
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
|
|
AstNode *cond = NULL;
|
|
AstNode *cond = NULL;
|
|
|
|
+ Token lib_name = {0};
|
|
|
|
+
|
|
|
|
+ switch (f->curr_token.kind) {
|
|
|
|
+ case Token_Ident:
|
|
|
|
+ lib_name = f->curr_token;
|
|
|
|
+ next_token(f);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ lib_name.pos = f->curr_token.pos;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (str_eq(lib_name.string, str_lit("_"))) {
|
|
|
|
+ syntax_error(lib_name, "Illegal #foreign_library name: `_`");
|
|
|
|
+ }
|
|
Token file_path = expect_token(f, Token_String);
|
|
Token file_path = expect_token(f, Token_String);
|
|
|
|
|
|
if (allow_token(f, Token_when)) {
|
|
if (allow_token(f, Token_when)) {
|
|
@@ -3334,7 +3358,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|
}
|
|
}
|
|
|
|
|
|
if (f->curr_proc == NULL) {
|
|
if (f->curr_proc == NULL) {
|
|
- s = make_foreign_library(f, hash_token, file_path, cond, true);
|
|
|
|
|
|
+ s = make_foreign_library(f, hash_token, file_path, lib_name, cond, true);
|
|
} else {
|
|
} else {
|
|
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
|
|
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
|
|
s = make_bad_decl(f, token, file_path);
|
|
s = make_bad_decl(f, token, file_path);
|
|
@@ -3343,6 +3367,21 @@ AstNode *parse_stmt(AstFile *f) {
|
|
return s;
|
|
return s;
|
|
} else if (str_eq(tag, str_lit("foreign_library"))) {
|
|
} else if (str_eq(tag, str_lit("foreign_library"))) {
|
|
AstNode *cond = NULL;
|
|
AstNode *cond = NULL;
|
|
|
|
+ Token lib_name = {0};
|
|
|
|
+
|
|
|
|
+ switch (f->curr_token.kind) {
|
|
|
|
+ case Token_Ident:
|
|
|
|
+ lib_name = f->curr_token;
|
|
|
|
+ next_token(f);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ lib_name.pos = f->curr_token.pos;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (str_eq(lib_name.string, str_lit("_"))) {
|
|
|
|
+ syntax_error(lib_name, "Illegal #foreign_library name: `_`");
|
|
|
|
+ }
|
|
Token file_path = expect_token(f, Token_String);
|
|
Token file_path = expect_token(f, Token_String);
|
|
|
|
|
|
if (allow_token(f, Token_when)) {
|
|
if (allow_token(f, Token_when)) {
|
|
@@ -3350,7 +3389,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|
}
|
|
}
|
|
|
|
|
|
if (f->curr_proc == NULL) {
|
|
if (f->curr_proc == NULL) {
|
|
- s = make_foreign_library(f, hash_token, file_path, cond, false);
|
|
|
|
|
|
+ s = make_foreign_library(f, hash_token, file_path, lib_name, cond, false);
|
|
} else {
|
|
} else {
|
|
syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope");
|
|
syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope");
|
|
s = make_bad_decl(f, token, file_path);
|
|
s = make_bad_decl(f, token, file_path);
|
|
@@ -3513,22 +3552,6 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-// // NOTE(bill): Returns true if it's added
|
|
|
|
-// bool try_add_foreign_library_path(Parser *p, String import_file) {
|
|
|
|
-// gb_mutex_lock(&p->mutex);
|
|
|
|
-
|
|
|
|
-// for_array(i, p->foreign_libraries) {
|
|
|
|
-// String import = p->foreign_libraries.e[i];
|
|
|
|
-// if (str_eq(import, import_file)) {
|
|
|
|
-// return false;
|
|
|
|
-// }
|
|
|
|
-// }
|
|
|
|
-// array_add(&p->foreign_libraries, import_file);
|
|
|
|
-// gb_mutex_unlock(&p->mutex);
|
|
|
|
-// return true;
|
|
|
|
-// }
|
|
|
|
-
|
|
|
|
gb_global Rune illegal_import_runes[] = {
|
|
gb_global Rune illegal_import_runes[] = {
|
|
'"', '\'', '`', ' ', '\t', '\r', '\n', '\v', '\f',
|
|
'"', '\'', '`', ' ', '\t', '\r', '\n', '\v', '\f',
|
|
'\\', // NOTE(bill): Disallow windows style filepaths
|
|
'\\', // NOTE(bill): Disallow windows style filepaths
|