aboutsummaryrefslogtreecommitdiff
path: root/src/parser.c
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-26 20:00:16 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-26 20:00:16 +0000
commite3e16f5d051c2b941d5e4ee1a64b235286a85cdf (patch)
treea145c1c0a2a2e9d0bb6111f92c6ddc3a79339df2 /src/parser.c
parentf47f25f9420e094f9eafe68b0844b860033da7cc (diff)
Library names - Only link with used foreign libraries
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c109
1 files changed, 66 insertions, 43 deletions
diff --git a/src/parser.c b/src/parser.c
index 10f2275f7..c208a260f 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -124,11 +124,12 @@ AstNodeArray make_ast_node_array(AstFile *f) {
AstNode *expr; \
}) \
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 { \
AstNode *type; \
@@ -302,6 +303,7 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
}) \
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
Token token, filepath; \
+ Token library_name; \
String base_dir; \
AstNode *cond; \
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);
result->ProcLit.type = type;
result->ProcLit.body = body;
result->ProcLit.tags = tags;
+ result->ProcLit.foreign_library = foreign_library;
result->ProcLit.foreign_name = foreign_name;
result->ProcLit.link_name = link_name;
return result;
@@ -1112,14 +1115,6 @@ AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArra
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 *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;
}
+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) {
Token prev = f->curr_token;
@@ -1316,7 +1321,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
case AstNode_EnumType:
return true;
case AstNode_ProcLit:
- return true;
+ return s->ProcLit.body != NULL;
case AstNode_ValueDecl:
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_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);
AstNode * parse_stmt(AstFile *f);
AstNode * parse_body(AstFile *f);
@@ -1508,7 +1513,7 @@ bool is_foreign_name_valid(String name) {
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
GB_ASSERT(tags != 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"))) {
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) {
*foreign_name = f->curr_token.string;
// TODO(bill): Check if valid string
@@ -1785,9 +1791,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
// Parse Procedure Type or Literal
case Token_proc: {
Token token = f->curr_token;
+ AstNode *foreign_library = NULL;
String foreign_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;
if (f->curr_token.kind == Token_OpenBrace) {
@@ -1800,11 +1807,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
body = parse_body(f);
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) {
- 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) {
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 results = {0};
@@ -2322,12 +2329,14 @@ AstNode *parse_proc_type(AstFile *f, String *foreign_name_, String *link_name_)
u64 tags = 0;
String foreign_name = {0};
String link_name = {0};
+ AstNode *foreign_library = NULL;
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);
}
@@ -2644,7 +2653,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
case Token_proc: {
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) {
syntax_error(token, "A procedure type cannot have tags");
}
@@ -3327,6 +3336,21 @@ AstNode *parse_stmt(AstFile *f) {
return s;
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
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);
if (allow_token(f, Token_when)) {
@@ -3334,7 +3358,7 @@ AstNode *parse_stmt(AstFile *f) {
}
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 {
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);
@@ -3343,6 +3367,21 @@ AstNode *parse_stmt(AstFile *f) {
return s;
} else if (str_eq(tag, str_lit("foreign_library"))) {
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);
if (allow_token(f, Token_when)) {
@@ -3350,7 +3389,7 @@ AstNode *parse_stmt(AstFile *f) {
}
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 {
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);
@@ -3513,22 +3552,6 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
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[] = {
'"', '\'', '`', ' ', '\t', '\r', '\n', '\v', '\f',
'\\', // NOTE(bill): Disallow windows style filepaths