aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/actualize.c67
-rw-r--r--src/ast.c12
-rw-r--r--src/compiler.c82
-rw-r--r--src/scope.c49
4 files changed, 113 insertions, 97 deletions
diff --git a/src/actualize.c b/src/actualize.c
index ebbffbb..941f9e3 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -327,6 +327,32 @@ static int eval_const_if(struct scope *scope, struct ast *node)
static int actualize_proc_sign(struct scope *scope, struct ast *proc);
+static int copy_scope(struct scope *to, struct scope *from)
+{
+ /** @todo handle duplicates */
+ foreach(visible, n, &from->symbols) {
+ struct ast *def = n->data;
+ if (!ast_flags(def, AST_FLAG_PUBLIC))
+ continue;
+
+ switch (def->k) {
+ case AST_PROC_DEF:
+ if (scope_add_proc(to, def))
+ return -1;
+ break;
+
+ case AST_VAR_DEF:
+ if (scope_add_var(to, def))
+ return -1;
+ break;
+
+ default: abort();
+ }
+ }
+
+ return 0;
+}
+
static int analyze_visibility(struct scope *scope, struct ast *node)
{
if (!node)
@@ -343,17 +369,19 @@ static int analyze_visibility(struct scope *scope, struct ast *node)
case AST_IMPORT: {
const char *file = import_file(node);
- int ret = process_file(&scope,
- (int)ast_flags(node, AST_FLAG_PUBLIC),
- file);
+ struct scope *child = process_file(file);
- if (ret == 0)
- return 0;
+ if (!child) {
+ semantic_info(scope->fctx, node, "imported here");
+ return -1;
+ }
- /** @todo should maybe make this some other type of error, kind
- * of too busy atm */
- semantic_info(scope->fctx, node, "imported here");
- return ret;
+ if (copy_scope(scope, child)) {
+ semantic_info(scope->fctx, node, "imported here");
+ return -1;
+ }
+
+ return 0;
}
case AST_IF: {
@@ -2118,22 +2146,6 @@ static int params_match(struct scope *scope, struct ast *base, struct ast *node)
return 1;
}
-/* slightly hacky but works well enough for now */
-static int trait_exported(struct scope *scope, struct ast *def)
-{
- assert(file_scope_find_type(scope, def->s) == def);
-
- while (!scope_flags(scope, SCOPE_FILE) && scope->parent)
- scope = scope->parent;
-
- assert(scope && scope_flags(scope, SCOPE_FILE));
- struct scope *parent = scope->parent;
- if (!parent)
- return true;
-
- return file_scope_find_type(parent, def->s) == def;
-}
-
static int expand_struct_body(struct act_state *state,
struct scope *scope,
struct ast *node,
@@ -2185,9 +2197,10 @@ static int expand_struct_body(struct act_state *state,
struct ast *def = type->d;
/* traits should only show up during the initial
* expansion, but should maybe make sure somehow */
- if (def->k == AST_TRAIT_DEF && !trait_exported(scope, def)) {
+ if (def->k == AST_TRAIT_DEF && !is_exported_type(scope,
+ def)) {
semantic_error(struct_scope->fctx, n,
- "trait used in pub def must also be exported");
+ "trait used in pub def must also be exported");
return -1;
}
}
diff --git a/src/ast.c b/src/ast.c
index 5ba8000..e4254da 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -424,15 +424,15 @@ struct ast *clone_ast(struct ast *n)
/* don't clone defers */
if (!(n->k == AST_BLOCK))
- if (n->a1)
- new->a1 = clone_ast_list(n->a1);
+ if (n->a1)
+ new->a1 = clone_ast_list(n->a1);
/* don't clone expanded body, just the raw one */
if (!(n->k == AST_TRAIT_DEF
- || n->k == AST_STRUCT_DEF
- || n->k == AST_STRUCT_CONT_DEF))
- if (n->a2)
- new->a2 = clone_ast_list(n->a2);
+ || n->k == AST_STRUCT_DEF
+ || n->k == AST_STRUCT_CONT_DEF))
+ if (n->a2)
+ new->a2 = clone_ast_list(n->a2);
if (n->a3)
new->a3 = clone_ast_list(n->a3);
diff --git a/src/compiler.c b/src/compiler.c
index 7ce6167..b4a6e9b 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -67,7 +67,7 @@ static char *read_file(const char *file, FILE *f)
* @param file File name to process.
* @return \c 0 if processing was succesful, non-zero value otherwise.
*/
-static int process(struct scope **parent, int public, const char *file)
+static int process(struct scope *scope, const char *file)
{
FILE *f = fopen(file, "rb");
if (!f) {
@@ -99,24 +99,10 @@ static int process(struct scope **parent, int public, const char *file)
ast_dump_list(0, tree);
- struct scope *scope = create_scope();
- if (!scope) {
- free((void *)buf);
- return -1;
- }
-
- if (public)
- scope_set_flags(scope, SCOPE_PUBLIC);
-
scope->fctx.fbuf = buf;
scope->fctx.fname = strdup(file);
scope_set_flags(scope, SCOPE_FILE);
- if (*parent)
- scope_add_scope(*parent, scope);
- else
- *parent = scope;
-
if (analyze_root(scope, tree))
return -1;
@@ -129,52 +115,26 @@ static int process(struct scope **parent, int public, const char *file)
#define MAP_NAME scopes
#include "ek/map.h"
-static int copy_scope(struct scope *to, struct scope *from)
-{
- /** @todo handle duplicates */
- foreach(visible, n, &from->symbols) {
- struct ast *def = n->data;
- if (!ast_flags(def, AST_FLAG_PUBLIC))
- continue;
-
- switch (def->k) {
- case AST_PROC_DEF:
- if (scope_add_proc(to, def))
- return -1;
- break;
-
- case AST_VAR_DEF:
- if (scope_add_var(to, def))
- return -1;
- break;
-
- default: abort();
- }
- }
-
- return 0;
-}
-
/* ugly global for now */
static struct scopes scopes;
static void destroy_scopes()
{
if (scopes_len(&scopes))
- foreach(scopes, n, &scopes) {
- free(n->key);
- }
+ foreach(scopes, n, &scopes) {
+ destroy_scope(n->data);
+ free(n->key);
+ }
scopes_destroy(&scopes);
}
-int process_file(struct scope **scope, int public, const char *file)
+struct scope *process_file(const char *file)
{
- int res = -1;
/** todo report failure allocating stuff maybe? */
struct res *r = res_create();
if (!r)
- return -1;
+ return NULL;
const char *base = ek_basename(file);
res_add(r, (void *)base);
@@ -203,37 +163,39 @@ int process_file(struct scope **scope, int public, const char *file)
struct scope **exists = scopes_find(&scopes, real);
if (exists) {
- if (copy_scope(*scope, *exists))
- goto out;
-
+ res_destroy(r);
free(real);
+ return *exists;
} else {
- if (process(scope, public, base))
+ struct scope *scope = create_scope();
+ if (process(scope, base)) {
+ destroy_scope(scope);
+ free(real);
goto out;
+ }
- scopes_insert(&scopes, real, *scope);
+ scopes_insert(&scopes, real, scope);
+ res_destroy(r);
+ return scope;
}
if (chdir(cwd)) {
error("couldn't change back to directory %s: %s\n", cwd,
- strerror(
- errno));
+ strerror(errno));
goto out;
}
- res = 0;
out:
res_destroy(r);
- return res;
+ return NULL;
}
int compile(const char *input) {
scopes = scopes_create();
int ret = -1;
- struct scope *root = NULL;
- if (process_file(&root, 0, input)) {
- destroy_scope(root);
+ struct scope *root = process_file(input);
+ if (!root) {
destroy_allocs();
destroy_scopes();
error("compilation of %s stopped due to errors", input);
@@ -241,14 +203,12 @@ int compile(const char *input) {
}
if ((ret = lower(root))) {
- destroy_scope(root);
destroy_allocs();
destroy_scopes();
error("compilation of %s stopped due to errors", input);
return ret;
}
- destroy_scope(root);
destroy_allocs();
destroy_scopes();
return 0;
diff --git a/src/scope.c b/src/scope.c
index 52028a8..282018c 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -39,6 +39,10 @@ struct scope *create_scope()
scope->macros = visible_create();
scope->types = visible_create();
+ scope->exported_symbols = exported_create();
+ scope->exported_macros = exported_create();
+ scope->exported_types = exported_create();
+
scope->number = counter++;
return scope;
}
@@ -59,9 +63,12 @@ void destroy_scope(struct scope *scope)
expanded_destroy(&scope->expanded);
+ exported_destroy(&scope->exported_symbols);
+ exported_destroy(&scope->exported_macros);
+ exported_destroy(&scope->exported_types);
+
struct scope *prev = scope->children, *cur;
- if (prev)
- do {
+ if (prev) do {
cur = prev->next;
destroy_scope(prev);
} while ((prev = cur));
@@ -87,7 +94,7 @@ struct ast **create_type(struct scope *scope, char *id, struct ast *type)
}
struct ast **create_expanded(struct scope *scope, struct ast *def,
- struct type *types, struct ast *expd)
+ struct type *types, struct ast *expd)
{
struct expanded_key key = {.def = def, .types = types};
return expanded_insert(&scope->expanded, key, expd);
@@ -449,3 +456,39 @@ void scope_add_scope(struct scope *parent, struct scope *child)
child->next = parent->children;
parent->children = child;
}
+
+bool is_exported_type(struct scope *scope, struct ast *def)
+{
+ struct ast **found = exported_find(&scope->exported_types, def);
+ if (found)
+ return true;
+
+ if (scope->parent)
+ return is_exported_type(scope->parent, def);
+
+ return false;
+}
+
+bool is_exported_symbol(struct scope *scope, struct ast *def)
+{
+ struct ast **found = exported_find(&scope->exported_symbols, def);
+ if (found)
+ return true;
+
+ if (scope->parent)
+ return is_exported_symbol(scope->parent, def);
+
+ return false;
+}
+
+bool is_exported_macro(struct scope *scope, struct ast *def)
+{
+ struct ast **found = exported_find(&scope->exported_macros, def);
+ if (found)
+ return true;
+
+ if (scope->parent)
+ return is_exported_macro(scope->parent, def);
+
+ return false;
+}