aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-11-13 18:05:33 +0200
committerKimplul <kimi.h.kuparinen@gmail.com>2023-11-13 18:05:33 +0200
commitb00da3db7c1d7f1e16b2e0446234dc42d54b8708 (patch)
tree3292fa94dfe02aad7036b7627e17f6980d2bcbc0
parent5b5f6321c743e9a521e45865312a76ae0bffe450 (diff)
downloadek-b00da3db7c1d7f1e16b2e0446234dc42d54b8708.tar.gz
ek-b00da3db7c1d7f1e16b2e0446234dc42d54b8708.zip
further simplification of scope concept
-rw-r--r--include/ek/actualize.h31
-rw-r--r--include/ek/ast.h159
-rw-r--r--include/ek/scope.h85
-rw-r--r--src/actualize.c520
-rw-r--r--src/ast.c541
-rw-r--r--src/debug.c81
-rw-r--r--src/parser.y12
-rw-r--r--src/scope.c995
8 files changed, 617 insertions, 1807 deletions
diff --git a/include/ek/actualize.h b/include/ek/actualize.h
index adc22ef..486f19e 100644
--- a/include/ek/actualize.h
+++ b/include/ek/actualize.h
@@ -51,28 +51,6 @@ void replace_param_types(struct ast_node *param,
struct ast_node *arg_type);
/**
- * Replace traitd type with actual type.
- *
- * @param type Templated type.
- * Keep in mind that a traitd struct retains all trait parameters, so
- * pass the struct itself.
- * @param param_type Template parameter type to replace.
- * @param arg_type Type to replace \p param_type with.
- */
-void init_trait_type(struct ast_node *type, struct ast_node *param_type,
- struct ast_node *arg_type);
-
-/**
- * Replace traitd parameter types.
- *
- * @param param List of parameters to replace traitd types for.
- * @param param_type Types that match this are replaced with \p arg_type.
- * @param arg_type Type to replace \p param_type with.
- */
-void init_trait_types(struct ast_node *param, struct ast_node *param_type,
- struct ast_node *arg_type);
-
-/**
* Extract trait type, that is strip pointer/expression/alias stuff
* and get the trait itself from the type.
*
@@ -118,13 +96,4 @@ int actualize_main(struct scope *scope);
*/
int actualize_temp_type(struct scope *scope, struct ast_node *type);
-/**
- * Expand traits, typeofs, aliases and try to get the most
- * basic representation.
- *
- * @param type Type to extract actual type from.
- * @return AST node of actual type.
- */
-struct ast_node *actual_type(struct ast_node *type);
-
#endif /* ANALYZE_H */
diff --git a/include/ek/ast.h b/include/ek/ast.h
index 421d247..6b19f88 100644
--- a/include/ek/ast.h
+++ b/include/ek/ast.h
@@ -10,7 +10,37 @@
* Abstract syntax tree handling.
*/
-#define AST_GET(x, y) x->x.y
+#define AST_ID(x) x->_id
+#define AST_IMPORT(x) x->_import
+#define AST_ALIAS(x) x->_alias
+#define AST_TRAIT(x) x->_trait
+#define AST_PROC(x) x->_proc
+#define AST_VAR(x) x->_var
+#define AST_STRUCT(x) x->_struct
+#define AST_ENUM(x) x->_enum
+#define AST_CALL(x) x->_call
+#define AST_CONST(x) x->_const
+#define AST_BLOCK(x) x->_block
+#define AST_ARR_ACCESS(x) x->_arr_access
+#define AST_MACRO_CONSTRUCT(x) x->_macro_construct
+#define AST_MACRO_EXPAND(x) x->_macro_expand
+#define AST_TYPE_CONSTRUCT(x) x->_type_construct
+#define AST_TYPE_EXPAND(x) x->_type_expand
+
+#define AST_TYPE(x) x->_type
+#define AST_ID_TYPE(x) x->_type._id
+#define AST_TRAIT_TYPE(x) x->_type._trait
+/** @todo is sign and proc type the same ? */
+#define AST_TYPEOF_TYPE(x) x->_type._typeof
+#define AST_PROC_TYPE(x) x->_type._proc
+#define AST_ARR_TYPE(x) x->_type._arr
+#define AST_SIGN_TYPE(x) x->_type._sign
+#define AST_ENUM_TYPE(x) x->_type._enum
+#define AST_UNION_TYPE(x) x->_type._union
+#define AST_STRUCT_TYPE(x) x->_type._struct
+/* might rename primitive to something else */
+#define AST_PRIMITIVE_TYPE(x) x->_type._primitive
+#define AST_PTR_TYPE(x) x->_type._ptr
/** Binary operands, that is they take two arguments and produce a result. */
enum ast_binops {
@@ -189,26 +219,17 @@ enum ast_const_kind {
enum ast_type_kind {
/** ID, can refer to pretty much anything. */
AST_TYPE_ID,
+ AST_TYPE_PRIMITIVE,
/** Array. */
AST_TYPE_ARR,
/** Typeof expression. */
AST_TYPE_TYPEOF,
/** Trait. */
AST_TYPE_TRAIT,
- /** Alias. */
- AST_TYPE_ALIAS,
- /** Member, that is type element of some structure. */
- AST_TYPE_MEMBER,
/** Pointer to a type. */
AST_TYPE_POINTER,
- /** Union. */
- AST_TYPE_UNION,
- /** Procedure, mainly used in trait definition. */
- AST_TYPE_PROC,
/** Structure. */
AST_TYPE_STRUCT,
- /** Type with type arguments. */
- AST_TYPE_GENERIC,
/** Enum. */
AST_TYPE_ENUM,
/** Signature, i.e. procedure signature. */
@@ -523,22 +544,36 @@ struct ast_type {
* AST_TYPE_POINTER and one AST_TYPE_ID.
*/
struct ast_node *next;
+ struct ast_node *as;
+ struct ast_node *aliased;
+
/** Data relevant to kind. */
union {
- /** Name of a type. */
- struct ast_node *id;
+ /** Name of a type, to be converted later. */
+ struct {
+ struct ast_node *id;
+ } _id;
+
+ struct {
+ struct ast_node *id;
+ } _primitive;
+
/** Array type. */
struct {
- /** Size of array. @todo element size? */
struct ast_node *size;
- } arr;
+ struct ast_node *base;
+ } _arr;
+
+ struct {
+ struct ast_node *base;
+ } _ptr;
+
/** Typeof. */
struct {
/** Expression to take type of. */
struct ast_node *expr;
- /** Type expression resolves to. */
- struct ast_node *actual;
- } typeo;
+ } _typeof;
+
/** Procedure. */
struct {
/** Name. */
@@ -547,67 +582,40 @@ struct ast_type {
struct ast_node *params;
/** Return type. */
struct ast_node *ret;
- } proc;
- /** Alias. */
- struct {
- /** Alias definition. */
- struct ast_node *alias;
- /** Type alias resolves to. */
- struct ast_node *actual;
- } alias;
- /** Enum member. */
- struct {
- /** Name of member. */
- struct ast_node *id;
- /** Expression to try to get member from. */
- struct ast_node *expr;
- } member;
+ } _proc;
+
/** Trait. */
struct {
/** Trait definition. */
- struct ast_node *trait;
- /** Type trait 'resolves' to. */
- struct ast_node *actual;
- } trait;
- /** Generic struct before actualization. */
- struct {
- /** Name of struct. */
- struct ast_node *id;
- /** Type arguments. @todo should this be parameters? */
- struct ast_node *args;
- } generic;
+ struct ast_node *def;
+ } _trait;
+
/** Structure. */
struct {
- /** Name of structure. */
- struct ast_node *id;
- /** Arguments for type parameters. */
- struct ast_node *impls;
- } struc;
+ /** Structure definition. */
+ struct ast_node *def;
+ } _struct;
+
/** Enumeration. */
struct {
- /** Name of enum. */
- struct ast_node *id;
- /** Type enum is convertible to. */
- struct ast_node *type;
- } enu;
+ /** Enum definition. */
+ struct ast_node *def;
+ } _enum;
+
/** Union. */
struct {
/** Name of union. */
struct ast_node *id;
/** Arguments for type parameters. */
struct ast_node *impls;
- } unio;
- /**
- * Signature.
- * Can be either a procedure or a lambda, to be
- * determined later.
- */
+ } _union;
+
struct {
/** Parameter types. */
struct ast_node *params;
/** Return type. */
struct ast_node *ret;
- } sign;
+ } _sign;
};
};
@@ -734,7 +742,7 @@ struct ast_node {
/** Data relevant to kind. */
union {
- struct ast_arr_access arr_access;
+ struct ast_arr_access _arr_access;
/** Binary operation. */
struct ast_binop binop;
/** Unary operation. */
@@ -744,10 +752,10 @@ struct ast_node {
/** Cast. */
struct ast_cast _cast;
/** Macro definition. */
- struct ast_macro_construct _macro;
+ struct ast_macro_construct _macro_construct;
struct ast_macro_expand _macro_expand;
- struct ast_type_construct type_construct;
- struct ast_type_expand type_expand;
+ struct ast_type_construct _type_construct;
+ struct ast_type_expand _type_expand;
/** Procedure definition. */
struct ast_proc _proc;
/** Goto. */
@@ -1167,17 +1175,6 @@ struct ast_node *gen_struct(struct ast_node *id, struct ast_node *generics,
struct ast_node *body);
/**
- * Generate union definition.
- *
- * @param id Name of union.
- * @param generics List of type parameters.
- * @param body Body of structure.
- * @return Corresponding AST node.
- */
-struct ast_node *gen_union(struct ast_node *id, struct ast_node *generics,
- struct ast_node *body);
-
-/**
* Generate enum member fetch.
*
* @param id Name of enum member to fetch.
@@ -1187,14 +1184,6 @@ struct ast_node *gen_union(struct ast_node *id, struct ast_node *generics,
struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type);
/**
- * Generate last element.
- * @todo might have to come up with a better name for this
- *
- * @return Corresponding AST node.
- */
-struct ast_node *gen_last();
-
-/**
* Generate empty AST node.
*
* @return Corresponding AST node.
@@ -1287,7 +1276,7 @@ int ast_flags(struct ast_node *node, enum ast_flag flags);
* @param data Extra data to pass to \p call.
* @return Whatever \p call returns.
*/
-int ast_call_on(int (*call)(struct ast_node *node, void *data),
+int ast_call_on(int (*call)(struct ast_node *, void *),
struct ast_node *node, void *data);
/**
diff --git a/include/ek/scope.h b/include/ek/scope.h
index 020aaaa..156788a 100644
--- a/include/ek/scope.h
+++ b/include/ek/scope.h
@@ -33,30 +33,14 @@ enum scope_flags {
* table later.
*/
struct visible {
+ /** Name of the visible node. */
+ struct ast_node *id;
/** AST node that is visible. */
struct ast_node *node;
- /** The owning scope of the object. */
- struct scope *owner;
/** Next visible object in the scope we're in. */
struct visible *next;
};
-/**
- * Scratch AST nodes. Implemented by a simple linked list.
- *
- * Meant to store temporary AST nodes that
- * won't be visible to other scopes, but should
- * be freed later.
- *
- * Mostly just cleans up resource management a bit.
- */
-struct scratch {
- /** Temporary AST node. */
- struct ast_node *node;
- /** Next scratch node. */
- struct scratch *next;
-};
-
/** Actualized nodes visible to scope. */
struct actual {
/** Actualized AST node. */
@@ -142,6 +126,11 @@ struct resolve_node {
struct ast_node *resolved;
};
+struct types {
+ struct ast_node *id;
+ struct ast_node *type;
+ struct ast_node *next;
+};
/**
* Scope.
@@ -176,31 +165,10 @@ struct scope {
*/
struct actual *actuals;
- /** For temp stuff. */
- struct scratch *scratch;
-
/** { types */
- /** Enums visible in scope. */
- struct visible *enums;
- /** Structs visible in scope. */
- struct visible *structs;
- /**
- * Aliases visible in scope.
- * @todo Alias handling could maybe be improved, currently there's a
- * fair bit of extra alias handling. Maybe separate semantic AST from
- * type AST?
- */
- struct visible *aliases;
- /** Builtins visible in scope. u8, i32, etc. */
- struct visible *builtins;
+ struct visible *types;
- /**
- * Traits visible in scope.
- * @todo choose common terminology, sometimes the same thing is referred
- * to as interfaces, sometimes templates, sometimes just type.
- */
- struct visible *traits;
/** } */
struct visible *type_constructs;
@@ -211,10 +179,6 @@ struct scope {
* @todo Could maybe add separate array list instead of a variable list?
*/
struct visible *vars;
- /** Macros visible in scope. */
- struct visible *macros;
- /** Procedures visible in scope. */
- struct visible *procs;
struct resolve *proc_resolve;
struct resolve *macro_resolve;
@@ -363,7 +327,7 @@ int scope_add_var(struct scope *scope, struct ast_node *var);
* @param type Type to add to scope.
* @return \c 0 when succesful, non-zero otherwise.
*/
-int scope_add_type(struct scope *scope, struct ast_node *type);
+int scope_add_type(struct scope *scope, struct ast_node *id, struct ast_node *type);
/**
* Add procedure to scope.
@@ -386,16 +350,6 @@ int scope_add_proc(struct scope *scope, struct ast_node *proc);
int scope_add_macro(struct scope *scope, struct ast_node *macro);
/**
- * Add alias to scope.
- * Propagates public aliases up the file scope chain as references.
- *
- * @param scope Scope to add alias to.
- * @param alias Alias to add to scope.
- * @return \c 0 when succesful, non-zero otherwise.
- */
-int scope_add_alias(struct scope *scope, struct ast_node *alias);
-
-/**
* Add template to scope.
* Propagates public templates up the file scope chain as references.
*
@@ -650,27 +604,6 @@ struct ast_node *scope_resolve_proc(struct scope *scope, struct ast_node *call);
struct ast_node *scope_resolve_call(struct scope *scope, struct ast_node *call);
/**
- * Try to resolve a type to a type in \p scope.
- *
- * @param scope Scope to look in.
- * @param type AST type node to try and match to an AST type node.
- * @return Pointer to the AST node corresponding to \p call if found,
- * otherwise \c NULL.
- */
-struct ast_node *scope_resolve_type(struct scope *scope, struct ast_node *type);
-
-/**
- * Try to resolve a type to a type visible to \p scope.
- *
- * @param scope Scope to look in.
- * @param type AST type node to try and match to an AST type node.
- * @return Pointer to the AST node corresponding to \p call if found,
- * otherwise \c NULL.
- */
-struct ast_node *file_scope_resolve_type(struct scope *scope,
- struct ast_node *type);
-
-/**
* Try to resolve a call to an AST node visible to \p scope.
*
* @param scope Scope to look in.
diff --git a/src/actualize.c b/src/actualize.c
index 7a9e13d..932fc7a 100644
--- a/src/actualize.c
+++ b/src/actualize.c
@@ -56,10 +56,10 @@ static enum act_flags act_flags(struct act_state *state, enum act_flags flags)
static int is_void(struct ast_node *type)
{
assert(type->node_type == AST_TYPE);
- if (type->_type.kind != AST_TYPE_ID)
+ if (AST_TYPE(type).kind != AST_TYPE_PRIMITIVE)
return 0;
- struct ast_node *id = type->_type.id;
+ struct ast_node *id = AST_PRIMITIVE_TYPE(type).id;
if (strcmp(id->_id.id, "void") != 0)
return 0;
@@ -81,41 +81,45 @@ static struct ast_node *void_type()
return NULL;
}
- struct ast_node *void_type = gen_type(AST_TYPE_ID, void_id, NULL, NULL);
+ struct ast_node *void_type = gen_type(AST_TYPE_PRIMITIVE, void_id, NULL, NULL);
if (!void_type) {
internal_error("couldn't allocate void type");
destroy_ast_node(void_id);
return NULL;
}
+ ast_set_flags(void_type, AST_FLAG_ACTUAL);
+
void_type->type = void_type;
return void_type;
}
-static struct ast_node *i64_type()
+static struct ast_node *i27_type()
{
- char *i64_str = strdup("i64");
- if (!i64_str) {
- internal_error("couldn't allocate i64 string");
+ char *i27_str = strdup("i27");
+ if (!i27_str) {
+ internal_error("couldn't allocate i27 string");
return NULL;
}
- struct ast_node *i64_id = gen_id(i64_str, NULL_LOC());
- if (!i64_id) {
- internal_error("couldn't allocate i64 id");
- free(i64_str);
+ struct ast_node *i27_id = gen_id(i27_str, NULL_LOC());
+ if (!i27_id) {
+ internal_error("couldn't allocate i27 id");
+ free(i27_str);
return NULL;
}
- struct ast_node *i64_type = gen_type(AST_TYPE_ID, i64_id, NULL, NULL);
- if (!i64_type) {
- internal_error("couldn't allocate i64 type");
- destroy_ast_node(i64_id);
+ struct ast_node *i27_type = gen_type(AST_TYPE_PRIMITIVE, i27_id, NULL, NULL);
+ if (!i27_type) {
+ internal_error("couldn't allocate i27 type");
+ destroy_ast_node(i27_id);
return NULL;
}
- i64_type->type = i64_type;
- return i64_type;
+ ast_set_flags(i27_type, AST_FLAG_ACTUAL);
+
+ i27_type->type = i27_type;
+ return i27_type;
}
static int push_defer(struct act_state *state, struct ast_node *expr)
@@ -320,9 +324,9 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
}
case AST_IMPORT: {
- const char *file = node->_import.file;
- ret |= process_file(&scope, ast_flags(node,
- AST_FLAG_PUBLIC), file);
+ const char *file = AST_IMPORT(node).file;
+ ret |= process_file(&scope,
+ ast_flags(node, AST_FLAG_PUBLIC), file);
destroy_ast_tree(node);
break;
}
@@ -340,22 +344,27 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
}
case AST_STRUCT: {
- ret |= scope_add_type(scope, node);
+ /* we shouldn't get any anonymous structs at this stage */
+ struct ast_node *id = AST_STRUCT(node).id;
+ ret |= scope_add_type(scope, id, node);
break;
}
case AST_ENUM: {
- ret |= scope_add_type(scope, node);
+ struct ast_node *id = AST_ENUM(node).id;
+ ret |= scope_add_type(scope, id, node);
break;
}
case AST_ALIAS: {
- ret |= scope_add_alias(scope, node);
+ struct ast_node *id = AST_ALIAS(node).id;
+ ret |= scope_add_type(scope, id, node);
break;
}
case AST_TRAIT: {
- ret |= scope_add_trait(scope, node);
+ struct ast_node *id = AST_TRAIT(node).id;
+ ret |= scope_add_type(scope, id, node);
break;
}
@@ -378,7 +387,7 @@ static int analyze_file_visibility(struct scope *scope, struct ast_node *node)
/* a block might be inserted by something, in which case jump
* down into it */
assert(ast_flags(node, AST_FLAG_UNHYGIENIC));
- ret = analyze(scope, node->_block.body);
+ ret = analyze(scope, AST_BLOCK(node).body);
break;
}
@@ -415,104 +424,19 @@ int analyze_root(struct scope *scope, struct ast_node *tree)
return 0;
}
-int trait_match(struct ast_node *a, struct ast_node *b)
-{
- while (a && a->_type.kind == AST_TYPE_TRAIT)
- a = a->_type.trait.actual;
-
- while (b && b->_type.kind == AST_TYPE_TRAIT)
- b = b->_type.trait.actual;
-
- return types_match(a, b);
-}
-
-static int alias_match(struct ast_node *a, struct ast_node *b)
-{
- while (a && a->_type.kind == AST_TYPE_ALIAS)
- a = a->_type.alias.actual;
-
- while (b && b->_type.kind == AST_TYPE_ALIAS)
- b = b->_type.alias.actual;
-
- return types_match(a, b);
-}
-
-static int pointer_match(struct ast_node *a, struct ast_node *b)
+static int structs_match(struct ast_node *a, struct ast_node *b)
{
- if (a->_type.kind != AST_TYPE_POINTER)
- return 0;
-
- if (b->_type.kind != AST_TYPE_POINTER)
- return 0;
-
- return types_match(a->_type.next, b->_type.next);
-}
-
-static int typeof_match(struct ast_node *a, struct ast_node *b)
-{
- while (a && a->_type.kind == AST_TYPE_TYPEOF)
- a = a->_type.typeo.actual;
-
- while (b && b->_type.kind == AST_TYPE_TYPEOF)
- b = b->_type.typeo.actual;
-
- return types_match(a, b);
-}
-
-static int struct_match(struct ast_node *a, struct ast_node *b)
-{
- if (!identical_ast_nodes(0, a->_type.struc.id, b->_type.struc.id))
- return 0;
-
- /* note a slight asymmetry, in that types on the right will match if
- * they don't have impls, but structs on the left will not. */
- if (!b->_type.struc.impls)
- return 1;
-
- if (!a->_type.struc.impls)
- return 0;
-
- struct ast_node *a_impls = a->_type.struc.impls;
- struct ast_node *b_impls = b->_type.struc.impls;
- while (a_impls && b_impls) {
- if (!types_match(a_impls, b_impls))
- return 0;
-
- b_impls = b_impls->next;
- a_impls = a_impls->next;
- }
-
- if (a_impls || b_impls)
- return 0;
-
- return 1;
+ /** @todo: iterate over elements in structure */
+ /** @todo: check tag as well? */
+ return 0;
}
-static int union_match(struct ast_node *a, struct ast_node *b)
+static int primitives_match(struct ast_node *a, struct ast_node *b)
{
- assert(a->_type.kind == AST_TYPE_UNION);
- assert(b->_type.kind == AST_TYPE_UNION);
-
- if (!identical_ast_nodes(0, a->_type.unio.id, b->_type.unio.id))
- return 0;
-
- if (!a->_type.unio.impls || !b->_type.unio.impls)
- return 1;
-
- struct ast_node *a_impls = a->_type.unio.impls;
- struct ast_node *b_impls = b->_type.unio.impls;
- while (a_impls && b_impls) {
- a_impls = a_impls->next;
- if (!types_match(a_impls, b_impls))
- return 0;
+ struct ast_node *a_id = AST_PRIMITIVE_TYPE(a).id;
+ struct ast_node *b_id = AST_PRIMITIVE_TYPE(b).id;
- b_impls = b_impls->next;
- }
-
- if (a_impls || b_impls)
- return 0;
-
- return 1;
+ return strcmp(AST_ID(a_id).id, AST_ID(b_id).id) == 0;
}
int types_match(struct ast_node *a, struct ast_node *b)
@@ -526,64 +450,25 @@ int types_match(struct ast_node *a, struct ast_node *b)
assert(a->node_type == AST_TYPE);
assert(b->node_type == AST_TYPE);
- if (a->_type.kind == AST_TYPE_TYPEOF ||
- b->_type.kind == AST_TYPE_TYPEOF) {
- if (typeof_match(a, b))
- return 1;
- return 0;
- }
-
- /* handle special cases that should match even with different type kinds */
- if (a->_type.kind == AST_TYPE_TRAIT ||
- b->_type.kind == AST_TYPE_TRAIT) {
- /* TODO: check trait type name */
- if (trait_match(a, b))
- return 1;
- return 0;
- }
-
- if (a->_type.kind == AST_TYPE_ALIAS ||
- b->_type.kind == AST_TYPE_ALIAS) {
- if (alias_match(a, b))
- return 1;
- return 0;
- }
-
- /* aliases etc. resolved, not if the kinds are different we must not
- * match */
- if (a->_type.kind != b->_type.kind)
- return 0;
-
- if (a->_type.kind == AST_TYPE_POINTER ||
- b->_type.kind == AST_TYPE_POINTER) {
- if (pointer_match(a, b))
- return 1;
+ /* typeofs match 'everything' */
+ if (AST_TYPE(a).kind == AST_TYPE_TYPEOF || AST_TYPE(b).kind == AST_TYPE_TYPEOF)
+ return 1;
+ /* if the type kind doesn't match, we're done. */
+ if (AST_TYPE(a).kind != AST_TYPE(b).kind)
return 0;
- }
- if (a->_type.kind == AST_TYPE_STRUCT ||
- b->_type.kind == AST_TYPE_STRUCT) {
- if (struct_match(a, b))
- return 1;
+ if (AST_TYPE(a).kind == AST_TYPE_STRUCT)
+ return structs_match(a, b);
- return 0;
- }
+ if (AST_TYPE(a).kind == AST_TYPE_POINTER)
+ return types_match(AST_PTR_TYPE(a).base,
+ AST_PTR_TYPE(b).base);
- if (a->_type.kind == AST_TYPE_UNION ||
- b->_type.kind == AST_TYPE_UNION) {
- if (union_match(a, b))
- return 1;
+ if (AST_TYPE(a).kind == AST_TYPE_PRIMITIVE)
+ return primitives_match(a, b);
- return 0;
- }
-
- /* from here on, we know that both types are identical */
- if (!identical_ast_nodes(0, a, b))
- return 0;
-
- /* TODO: maybe implement some kind of recursion flag? */
- return 1; // types_match(a->_type.next, b->_type.next);
+ return 0;
}
static int _replace_id(struct ast_node *node, void *data)
@@ -662,31 +547,8 @@ struct ast_node *extract_trait(struct ast_node *type)
static void actualize_trait_types(struct ast_node *params,
struct ast_node *args)
{
- /* replace parameter types with argument types */
- if (args)
- do {
- assert(params->type);
- struct ast_node *trait = extract_trait(
- params->type);
- if (trait) {
- /* at this point we know that the types will
- * match, otherwise match_proc and friends
- * fucked up */
- struct ast_node *type = params->type;
- struct ast_node *base = args->type;
- while (type != trait) {
- type = type->_type.next;
- base = base->_type.next;
- assert(type);
- assert(base);
- }
-
- trait->_type.trait.actual = base;
- }
- params = params->next;
- args = args->next;
- } while (args && params);
-
+ /** @todo replace trait types with arg types, should probably be merged
+ * */
/* TODO: this might not hold in variadic functions... */
assert(!args && !params);
}
@@ -701,16 +563,10 @@ static int actualize_proc_call(struct act_state *state,
struct ast_node *sign = proc->type;
assert(sign->node_type == AST_TYPE);
- call->type = sign->_type.sign.ret;
+ call->type = AST_SIGN_TYPE(sign).ret;
return 0;
}
- if (ast_flags(proc, AST_FLAG_VARIADIC)) {
- semantic_error(scope->fctx, proc,
- "variadic procs not yet implemented");
- return -1;
- }
-
if (act_flags(state, ACT_ONLY_TYPES)) {
/* TODO: better cleanup */
/* at this point we're really only interested in the return
@@ -722,11 +578,6 @@ static int actualize_proc_call(struct act_state *state,
return -1;
}
- if (scope_add_scratch(scope, sign)) {
- internal_error("failed adding signature to scratch");
- return -1;
- }
-
struct scope *tmp = create_scope();
if (!tmp) {
internal_error(
@@ -738,7 +589,7 @@ static int actualize_proc_call(struct act_state *state,
* example, we want to use that file's scope */
scope_add_scope(proc->scope, tmp);
- struct ast_node *params = sign->_type.sign.params;
+ struct ast_node *params = AST_SIGN_TYPE(sign).params;
struct ast_node *args = call->_call.args;
/* fuck, analyze_proc gobbles up the return type typeof */
actualize_trait_types(params, args);
@@ -746,7 +597,7 @@ static int actualize_proc_call(struct act_state *state,
if (actualize(state, tmp, sign))
return -1;
- call->type = sign->_type.sign.ret;
+ call->type = AST_SIGN_TYPE(sign).ret;
return 0;
}
@@ -760,14 +611,14 @@ static int actualize_proc_call(struct act_state *state,
}
struct ast_node *sign = def->_proc.sign;
- struct ast_node *params = sign->_type.sign.params;
+ struct ast_node *params = AST_SIGN_TYPE(sign).params;
struct ast_node *args = call->_call.args;
actualize_trait_types(params, args);
if (actualize(state, def->scope, def))
return -1;
- call->type = sign->_type.sign.ret;
+ call->type = AST_SIGN_TYPE(sign).ret;
return 0;
}
@@ -775,24 +626,24 @@ static int actualize_macro_call(struct act_state *state,
struct scope *scope, struct ast_node *call,
struct ast_node *macro)
{
- assert(call->node_type == AST_CALL && macro->node_type == AST_MACRO_EXPAND);
+ assert(call->node_type == AST_CALL && macro->node_type == AST_MACRO_CONSTRUCT);
if (ast_flags(macro, AST_FLAG_VARIADIC)) {
semantic_error(scope->fctx, macro,
"variadic macros not yet implemented");
return -1;
}
- struct ast_node *body = clone_ast_node(macro->_macro.body);
+ struct ast_node *body = clone_ast_node(AST_MACRO_CONSTRUCT(macro).body);
if (!body) {
- internal_error("failed allocating body for macro call");
+ internal_error("failed allocating body for macro expansion");
return -1;
}
body->scope = call->scope;
body->next = call->next;
- struct ast_node *param = macro->_macro.params;
- struct ast_node *arg = call->_call.args;
+ struct ast_node *param = AST_MACRO_CONSTRUCT(macro).params;
+ struct ast_node *arg = AST_CALL(call).args;
/* TODO: actual replacements */
while (param && arg) {
@@ -957,7 +808,7 @@ static int actualize_proc(struct act_state *state,
/* actualize body */
ret |= actualize(&new_state, sign->scope, actual->_proc.body);
if (!act_flags(&new_state, ACT_HAS_RETURN)) {
- if (!is_void(sign->_type.sign.ret)) {
+ if (!is_void(AST_SIGN_TYPE(sign).ret)) {
semantic_error(scope->fctx, actual,
"no return with non-void return type");
ret = -1;
@@ -1013,8 +864,6 @@ static int actualize_binop(struct act_state *state,
return -1;
}
- /* TODO: slightly unsure how I'll handle aliases, maybe the types should
- * be actualized to the aliased values as well? */
if (!types_match(left->type, right->type)) {
char *left_type = type_str(left);
char *right_type = type_str(right);
@@ -1083,7 +932,9 @@ static int actualize_id(struct act_state *state,
{
UNUSED(state);
assert(id && id->node_type == AST_ID);
- struct ast_node *decl = file_scope_find(scope, id);
+ /** @todo at the moment we always assume an ID is a variable, but stuff
+ * like function callbacks should be added in the future */
+ struct ast_node *decl = file_scope_find_var(scope, id);
if (!decl) {
semantic_error(scope->fctx, id, "no such object");
return -1;
@@ -1188,69 +1039,50 @@ static int actualize_type(struct act_state *state,
EXIT_ACT(-1);
}
- switch (type->_type.kind) {
+ switch (AST_TYPE(type).kind) {
case AST_TYPE_ID: {
/* type IDs can really only be aliases to something else, or if
* they're missing, void */
- struct ast_node *id = type->_type.id;
- if (!id)
+ if (!AST_ID_TYPE(type).id) {
/* no ID means void */
- type->_type.id = gen_id(strdup("void"), NULL_LOC());
-
- type->loc = id->loc;
+ AST_ID_TYPE(type).id = gen_id(strdup("void"), NULL_LOC());
+ }
- struct ast_node *exists = file_scope_resolve_type(scope, type);
+ struct ast_node *exists = file_scope_find_type(scope, AST_ID_TYPE(type).id);
if (!exists) {
semantic_error(scope->fctx, type, "no such type");
EXIT_ACT(-1);
}
- /* nothing to do, except maybe check that types are actually
- * identical? */
- if (exists->node_type == AST_TYPE)
+ if (exists->node_type == AST_TYPE) {
+ assert(AST_TYPE(exists).kind == AST_TYPE_PRIMITIVE);
+ AST_TYPE(type) = AST_TYPE(exists);
break;
+ }
- assert(exists->node_type == AST_ALIAS
- || exists->node_type == AST_TRAIT
- || exists->node_type == AST_STRUCT
- || exists->node_type == AST_ENUM);
/* actualize whatever type we have on demand, either alias or
* trait */
if (!ast_flags(exists, AST_FLAG_ACTUAL))
if (actualize(state, exists->scope, exists))
EXIT_ACT(-1);
- assert(type->_type.next == NULL);
- destroy_ast_node(type->_type.id);
+ assert(AST_TYPE(type).next == NULL);
+ destroy_ast_node(AST_ID_TYPE(type).id);
if (exists->node_type == AST_ALIAS) {
- /* TODO: check if this is good enough */
- type->_type.kind = AST_TYPE_ALIAS;
- type->_type.alias.alias = exists;
- type->_type.alias.actual = exists->_alias.type;
+ AST_TYPE(type).aliased = exists;
+ AST_TYPE(type) = AST_TYPE(exists);
}
else if (exists->node_type == AST_TRAIT) {
- type->_type.kind = AST_TYPE_TRAIT;
- type->_type.trait.trait = exists;
- /* this should be populated later */
- type->_type.trait.actual = NULL;
+ /* this is kind of weird, have to think about it */
+ AST_TYPE(type) = AST_TYPE(exists);
}
else if (exists->node_type == AST_STRUCT) {
- /* I think, will still have to TODO: check */
- type->_type.kind = AST_TYPE_STRUCT;
- type->_type.struc.id =
- clone_ast_node(exists->_struct.id);
- /* should be populated later */
- type->_type.struc.impls = NULL;
+ AST_TYPE(type) = AST_TYPE(exists);
}
else if (exists->node_type == AST_ENUM) {
- type->_type.kind = AST_TYPE_ENUM;
- type->_type.enu.id = clone_ast_node(exists->_enum.id);
- type->_type.enu.type = exists->_enum.type;
+ AST_TYPE(type) = AST_TYPE(exists);
}
- if (ast_flags(exists, AST_FLAG_GENERIC))
- ast_set_flags(type, AST_FLAG_GENERIC);
-
break;
}
@@ -1259,7 +1091,7 @@ static int actualize_type(struct act_state *state,
break;
case AST_TYPE_TYPEOF: {
- struct ast_node *expr = type->_type.typeo.expr;
+ struct ast_node *expr = AST_TYPEOF_TYPE(type).expr;
/* TODO: expressions in top-level type declarations should
* probably be checked for, as we might not want to accidentally
* actualize procedure calls? */
@@ -1270,7 +1102,8 @@ static int actualize_type(struct act_state *state,
* anything dumb like that, but I would feel better if I figure
* out some check */
assert(type->_type.next == NULL);
- type->_type.typeo.actual = expr->type;
+ /** @todo add in some 'from' field for this situation? */
+ type->type = expr->type;
break;
}
@@ -1280,14 +1113,14 @@ static int actualize_type(struct act_state *state,
break;
case AST_TYPE_SIGN: {
- struct ast_node *params = type->_type.sign.params;
- struct ast_node *ret = type->_type.sign.ret;
+ struct ast_node *params = AST_SIGN_TYPE(type).params;
+ struct ast_node *ret = AST_SIGN_TYPE(type).ret;
if (actualize(state, scope, params))
EXIT_ACT(-1);
if (!ret)
- ret = type->_type.sign.ret = void_type();
+ ret = AST_SIGN_TYPE(type).ret = void_type();
if (actualize(state, scope, ret))
EXIT_ACT(-1);
@@ -1300,6 +1133,11 @@ static int actualize_type(struct act_state *state,
break;
}
+ case AST_TYPE_PRIMITIVE: {
+ assert(ast_flags(type, AST_FLAG_ACTUAL));
+ break;
+ }
+
default:
semantic_error(scope->fctx, type, "unimplemented type");
EXIT_ACT(-1);
@@ -1324,26 +1162,22 @@ static int actualize_empty(struct act_state *state,
node->type = gen_type(AST_TYPE_ID, void_id, NULL, NULL);
if (!node->type) {
- scope_add_scratch(scope, void_id);
internal_error("couldn't allocate type for empty statement\n");
return -1;
}
- scope_add_scratch(scope, node->type);
return 0;
}
static int integral_type(struct ast_node *type)
{
assert(type->node_type == AST_TYPE);
- if (type->_type.kind == AST_TYPE_ALIAS)
- return integral_type(type->_type.alias.actual);
-
- if (type->_type.kind != AST_TYPE_ID)
+ if (AST_TYPE(type).kind != AST_TYPE_PRIMITIVE)
return 0;
/* here would be awesome with an enum of our base types */
- const char *type_str = type->_type.id->_id.id;
+ struct ast_node *primitive = AST_PRIMITIVE_TYPE(type).id;
+ const char *type_str = AST_ID(primitive).id;
if (strcmp(type_str, "u8"))
return 1;
@@ -1397,7 +1231,8 @@ static int pointer_conversion(struct ast_node *a, struct ast_node *b)
if (b->_type.kind != AST_TYPE_ID)
return 0;
- struct ast_node *id = b->_type.id;
+ struct ast_node *id = AST_ID_TYPE(b).id;
+ /* there's gotta be a better way */
if (strcmp(id->_id.id, "usize") == 0)
return 1;
}
@@ -1545,53 +1380,21 @@ static int init_struct(struct act_state *state, struct scope *scope,
return ret;
}
-struct ast_node *actual_type(struct ast_node *type)
-{
- assert(type->node_type == AST_TYPE);
- if (type->_type.kind == AST_TYPE_ALIAS) {
- if (type->_type.alias.actual)
- return actual_type(type->_type.alias.actual);
-
- return type;
- }
-
- if (type->_type.kind == AST_TYPE_TRAIT) {
- if (type->_type.trait.actual)
- return actual_type(type->_type.trait.actual);
-
- return type;
- }
-
- if (type->_type.kind == AST_TYPE_TYPEOF) {
- if (type->_type.typeo.actual)
- return actual_type(type->_type.typeo.actual);
-
- return type;
- }
-
- return type;
-}
-
static int actualize_struct_init_cast(struct act_state *state,
struct scope *scope,
struct ast_node *init,
struct ast_node *actual)
{
- struct ast_node *id = actual->_type.struc.id;
- struct ast_node *exists = file_scope_resolve_type(scope, id);
- assert(exists);
- assert(ast_flags(exists, AST_FLAG_ACTUAL));
-
- return init_struct(state, scope, exists, init);
+ struct ast_node *def = AST_STRUCT_TYPE(actual).def;
+ return init_struct(state, scope, def, init);
}
static int actualize_init_cast(struct act_state *state,
struct scope *scope, struct ast_node *init,
struct ast_node *type)
{
- struct ast_node *actual = actual_type(type);
- if (actual->_type.kind == AST_TYPE_STRUCT)
- return actualize_struct_init_cast(state, scope, init, actual);
+ if (AST_TYPE(type).kind == AST_TYPE_STRUCT)
+ return actualize_struct_init_cast(state, scope, init, type);
semantic_error(scope->fctx, type,
"type is not a struct");
@@ -1694,9 +1497,7 @@ static int actualize_const(struct act_state *state, struct scope *scope,
assert(cons->node_type == AST_CONST);
if (cons->_const.kind == AST_CONST_INTEGER) {
/* error checking would be doog */
- cons->type = gen_type(AST_TYPE_ID, gen_id(strdup("i64"), NULL_LOC()),
- NULL, NULL);
- scope_add_scratch(scope, cons->type);
+ cons->type = i27_type();
return 0;
}
@@ -1711,9 +1512,13 @@ static int actualize_alias(struct act_state *state, struct scope *scope,
* aliases might be a bit cumbersome to work with. Still, this works
* well enough I suppose. */
assert(alias->node_type == AST_ALIAS);
+ if (ast_flags(alias, AST_FLAG_INIT)) {
+ semantic_error(scope->fctx, alias, "alias loop");
+ return -1;
+ }
+
ast_set_flags(alias, AST_FLAG_INIT);
- /* TODO: alias loops? */
- if (actualize(state, scope, alias->_alias.type)) {
+ if (actualize(state, scope, AST_ALIAS(alias).type)) {
/* usually we don't want to output errors upon errors, but this
* is likely a useful message as it might show where a loop is
* occuring */
@@ -1721,16 +1526,7 @@ static int actualize_alias(struct act_state *state, struct scope *scope,
return -1;
}
- /* TODO: is this hacky? */
- if (!scope_flags(scope, SCOPE_FILE)) {
- if (scope_add_alias(scope, alias))
- return -1;
- }
-
ast_set_flags(alias, AST_FLAG_ACTUAL);
- alias->type = gen_type(AST_TYPE_ALIAS, NULL,
- alias->_alias.id, alias->_alias.type);
- scope_add_scratch(scope, alias->type);
return 0;
}
@@ -1777,7 +1573,6 @@ static int actualize_defer(struct act_state *state,
return -1;
node->type = void_type();
- scope_add_scratch(scope, node->type);
return 0;
}
@@ -1794,13 +1589,12 @@ static int actualize_return(struct act_state *state, struct scope *scope,
}
else {
node->type = void_type();
- if (scope_add_scratch(scope, node->type))
- return -1;
}
assert(state->cur_proc);
struct ast_node *cur_proc = state->cur_proc;
- struct ast_node *ret = cur_proc->_proc.sign->_type.sign.ret;
+ struct ast_node *sign = AST_PROC(cur_proc).sign;
+ struct ast_node *ret = AST_SIGN_TYPE(sign).ret;
if (!types_match(node->type, ret)) {
char *rt = type_str(ret);
char *et = type_str(node);
@@ -1882,7 +1676,6 @@ static int actualize_goto(struct act_state *state, struct scope *scope,
/* clone all defers as we don't know where the label might be */
node->_goto.defers = clone_defers(state, NULL);
node->type = void_type();
- scope_add_scratch(scope, node->type);
struct ast_node *label = find_label(state, node->_goto.label);
/* this is a jump backwards, i.e. we can already do it */
@@ -1922,7 +1715,6 @@ static int actualize_label(struct act_state *state, struct scope *scope,
/* clone all defers */
node->_label.defers = clone_defers(state, NULL);
node->type = void_type();
- scope_add_scratch(scope, node->type);
actualize_goto_defers(state, node);
return 0;
@@ -2011,7 +1803,6 @@ static int actualize_struct(struct act_state *state,
/* cloning slightly odd, but I guess it's fine? */
struct ast_node *clone_id = clone_ast_node(node->_struct.id);
node->type = gen_type(AST_TYPE_STRUCT, clone_id, NULL, NULL);
- scope_add_scratch(scope, node->type);
ast_set_flags(node, AST_FLAG_ACTUAL);
return 0;
@@ -2022,17 +1813,14 @@ static int actualize_struct(struct act_state *state,
* structures or traits. */
static int has_members(struct ast_node *type)
{
- if (type->_type.kind == AST_TYPE_ALIAS)
- return has_members(type->_type.alias.actual);
-
- if (type->_type.kind == AST_TYPE_POINTER)
- type = type->_type.next;
+ if (AST_TYPE(type).kind == AST_TYPE_POINTER)
+ type = AST_TYPE(type).next;
/* most likely */
- if (type->_type.kind == AST_TYPE_STRUCT)
+ if (AST_TYPE(type).kind == AST_TYPE_STRUCT)
return 1;
- if (type->_type.kind == AST_TYPE_TRAIT)
+ if (AST_TYPE(type).kind == AST_TYPE_TRAIT)
return 1;
return 0;
@@ -2127,10 +1915,10 @@ static int actualize_fetch(struct act_state *state, struct scope *scope,
}
struct ast_node *id = fetch->_fetch.id;
- struct ast_node *enu = file_scope_resolve_type(scope, type->_type.id);
- assert(enu);
+ struct ast_node *def = file_scope_find_type(scope, AST_ID_TYPE(type).id);
+ assert(def);
- struct ast_node *member = lookup_enum_member(enu, id);
+ struct ast_node *member = lookup_enum_member(def, id);
if (!member) {
char *estr = type_str(type);
semantic_error(scope->fctx, id, "no such member in enum %s");
@@ -2138,7 +1926,7 @@ static int actualize_fetch(struct act_state *state, struct scope *scope,
return -1;
}
- fetch->type = enu->type;
+ fetch->type = def->type;
return 0;
}
@@ -2152,7 +1940,7 @@ static int actualize_enum(struct act_state *state, struct scope *scope,
/* TODO: here we could save space by choosing the smallest type that
* fits */
if (!type) {
- type = i64_type();
+ type = i27_type();
node->_enum.type = type;
} else if (actualize(state, enum_scope, type))
return -1;
@@ -2250,16 +2038,13 @@ static int actualize(struct act_state *state, struct scope *scope,
int actualize_main(struct scope *root)
{
- /* should maybe try and figure out a shorthand for this */
- /* especially if I try to find procs by signature as well */
- struct ast_node main_id = {0};
- main_id.node_type = AST_ID;
- main_id._id.id = "main";
+ struct ast_node *main_id = gen_id(strdup("main"), NULL_LOC());
+ struct ast_node *main_call = gen_call(main_id, NULL);
struct act_state state = {0};
/* skip checking signature for now */
- struct ast_node *main = file_scope_find_proc(root, &main_id);
+ struct ast_node *main = file_scope_resolve_call(root, main_call);
if (!main) {
/* libraries are not really compilable... */
error("no main");
@@ -2287,27 +2072,19 @@ void replace_type(struct ast_node *type, struct ast_node *from,
/* TODO: unsure if this is everything */
switch (type->_type.kind) {
case AST_TYPE_ID:
- destroy_ast_node(type->_type.id);
+ destroy_ast_node(AST_ID_TYPE(type).id);
break;
case AST_TYPE_STRUCT:
- destroy_ast_node(type->_type.struc.id);
+ destroy_ast_node(AST_STRUCT_TYPE(type).def);
break;
case AST_TYPE_ENUM:
- destroy_ast_node(type->_type.enu.id);
- break;
-
- case AST_TYPE_UNION:
- destroy_ast_node(type->_type.unio.id);
- break;
-
- case AST_TYPE_PROC:
- destroy_ast_node(type->_type.proc.id);
+ destroy_ast_node(AST_ENUM_TYPE(type).def);
break;
case AST_TYPE_TYPEOF:
- destroy_ast_node(type->_type.typeo.expr);
+ destroy_ast_node(AST_TYPEOF_TYPE(type).expr);
break;
default:
@@ -2334,37 +2111,6 @@ void replace_param_types(struct ast_node *param, struct ast_node *param_type,
}
}
-void init_trait_type(struct ast_node *type, struct ast_node *param_type,
- struct ast_node *arg_type)
-{
- if (!types_match(type, param_type))
- return;
-
- struct ast_node *trait = extract_trait(type);
- if (trait) {
- /* TODO: this shares a fair bit of similarities with
- * actualize_trait_types, could probably create a common
- * backend? */
- while (type != trait) {
- type = param_type->_type.next;
- arg_type = arg_type->_type.next;
- assert(type);
- assert(arg_type);
- }
-
- trait->_type.trait.actual = arg_type;
- }
-}
-
-void init_trait_types(struct ast_node *params, struct ast_node *param_type,
- struct ast_node *arg_type)
-{
- while (params) {
- init_trait_type(params->type, param_type, arg_type);
- params = params->next;
- }
-}
-
int actualize_temp_type(struct scope *scope, struct ast_node *type)
{
struct act_state state;
diff --git a/src/ast.c b/src/ast.c
index 5a37254..b3164c0 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -17,6 +17,8 @@
#include <ek/ast.h>
#include <ek/scope.h>
+/** @todo alloc should maybe also keep track of all nodes in a vector or
+ * something and mass free all AST at a time to keep my sanity */
#define ALLOC_NODE(n, type) \
struct ast_node *n = calloc(1, sizeof(struct ast_node)); \
if (!n) { \
@@ -38,8 +40,8 @@ struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, str
{
ALLOC_NODE(n, "arr_access");
n->node_type = AST_ARR_ACCESS;
- n->arr_access.base = base;
- n->arr_access.idx = idx;
+ AST_ARR_ACCESS(n).base = base;
+ AST_ARR_ACCESS(n).idx = idx;
n->loc = loc;
return n;
}
@@ -47,8 +49,8 @@ struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, str
void destroy_arr_access(struct ast_node *arr_access)
{
assert(arr_access->node_type == AST_ARR_ACCESS);
- destroy_ast_node(AST_GET(arr_access, base));
- destroy_ast_node(AST_GET(arr_access, idx));
+ destroy_ast_node(AST_ARR_ACCESS(arr_access).base);
+ destroy_ast_node(AST_ARR_ACCESS(arr_access).idx);
free(arr_access);
}
@@ -77,18 +79,18 @@ struct ast_node *gen_type_construct(struct ast_node *id,
{
ALLOC_NODE(n, "type_construct");
n->node_type = AST_TYPE_CONSTRUCT;
- n->type_construct.id = id;
- n->type_construct.params = params;
- n->type_construct.body = body;
+ AST_TYPE_CONSTRUCT(n).id = id;
+ AST_TYPE_CONSTRUCT(n).params = params;
+ AST_TYPE_CONSTRUCT(n).body = body;
n->loc = loc;
return n;
}
void destroy_type_construct(struct ast_node *type_construct)
{
- destroy_ast_node(AST_GET(type_construct, id));
- destroy_ast_node(AST_GET(type_construct, params));
- destroy_ast_node(AST_GET(type_construct, body));
+ destroy_ast_node(AST_TYPE_CONSTRUCT(type_construct).id);
+ destroy_ast_node(AST_TYPE_CONSTRUCT(type_construct).params);
+ destroy_ast_node(AST_TYPE_CONSTRUCT(type_construct).body);
free(type_construct);
}
@@ -98,8 +100,8 @@ struct ast_node *gen_type_expand(struct ast_node *id,
{
ALLOC_NODE(n, "type_expand");
n->node_type = AST_TYPE_EXPAND;
- n->type_expand.id = id;
- n->type_expand.args = args;
+ AST_TYPE_EXPAND(n).id = id;
+ AST_TYPE_EXPAND(n).args = args;
n->loc = loc;
return n;
}
@@ -107,8 +109,8 @@ struct ast_node *gen_type_expand(struct ast_node *id,
void destroy_type_expand(struct ast_node *n)
{
assert(n->node_type == AST_TYPE_EXPAND);
- destroy_ast_node(n->type_expand.args);
- free((void *)n->type_expand.id);
+ destroy_ast_node(AST_TYPE_EXPAND(n).id);
+ destroy_ast_node(AST_TYPE_EXPAND(n).args);
free(n);
}
@@ -399,9 +401,9 @@ struct ast_node *gen_macro_construct(struct ast_node *id,
{
ALLOC_NODE(n, "macro_construct");
n->node_type = AST_MACRO_CONSTRUCT;
- n->_macro.id = id;
- n->_macro.params = params;
- n->_macro.body = body;
+ AST_MACRO_CONSTRUCT(n).id = id;
+ AST_MACRO_CONSTRUCT(n).params = params;
+ AST_MACRO_CONSTRUCT(n).body = body;
n->loc = id->loc;
return n;
}
@@ -409,9 +411,9 @@ struct ast_node *gen_macro_construct(struct ast_node *id,
void destroy_macro_construct(struct ast_node *macro)
{
assert(macro->node_type == AST_MACRO_CONSTRUCT);
- destroy_ast_node(macro->_macro.id);
- DESTROY_LIST(macro->_macro.params);
- DESTROY_LIST(macro->_macro.body);
+ destroy_ast_node(AST_MACRO_CONSTRUCT(macro).id);
+ DESTROY_LIST(AST_MACRO_CONSTRUCT(macro).params);
+ DESTROY_LIST(AST_MACRO_CONSTRUCT(macro).body);
free(macro);
}
@@ -475,77 +477,51 @@ void destroy_case(struct ast_node *cas)
free(cas);
}
-struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id,
- struct ast_node *expr, struct ast_node *ret)
+struct ast_node *gen_type(enum ast_type_kind kind,
+ struct ast_node *t0,
+ struct ast_node *t1,
+ struct ast_node *t2)
{
ALLOC_NODE(n, "type");
n->node_type = AST_TYPE;
- n->_type.kind = kind;
+ AST_TYPE(n).kind = kind;
switch (kind) {
- case AST_TYPE_GENERIC:
- n->_type.generic.id = id;
- n->_type.generic.args = expr;
- n->loc = id->loc;
- break;
-
- case AST_TYPE_MEMBER:
- n->_type.member.id = id;
- n->_type.member.expr = expr;
- n->loc = id->loc;
- break;
-
- case AST_TYPE_ALIAS:
- n->_type.alias.alias = expr;
- n->_type.alias.actual = ret;
- n->loc = expr->loc;
- break;
+ case AST_TYPE_PRIMITIVE:
+ AST_PRIMITIVE_TYPE(n).id = t0;
+ break;
case AST_TYPE_TRAIT:
- n->_type.trait.trait = expr;
- n->_type.trait.actual = ret;
- n->loc = expr->loc;
+ AST_TRAIT_TYPE(n).def = t0;
break;
case AST_TYPE_ID:
- n->_type.id = id;
- n->loc = id->loc;
+ AST_ID_TYPE(n).id = t0;
break;
case AST_TYPE_ARR:
- n->_type.arr.size = expr;
- if (expr)
- n->loc = expr->loc;
+ AST_ARR_TYPE(n).size = t0;
+ AST_ARR_TYPE(n).base = t1;
break;
case AST_TYPE_TYPEOF:
- n->_type.typeo.expr = expr;
- n->loc = expr->loc;
+ AST_TYPEOF_TYPE(n).expr = t0;
break;
case AST_TYPE_POINTER:
+ AST_PTR_TYPE(n).base = t0;
break;
- case AST_TYPE_PROC:
- n->_type.proc.params = expr;
- n->_type.proc.ret = ret;
- break;
-
- case AST_TYPE_UNION:
case AST_TYPE_STRUCT:
- n->_type.struc.id = id;
- n->_type.struc.impls = expr;
- n->loc = id->loc;
+ AST_STRUCT_TYPE(n).def = t0;
break;
case AST_TYPE_ENUM:
- n->_type.enu.id = id;
- n->_type.struc.impls = expr;
- n->loc = id->loc;
+ AST_ENUM_TYPE(n).def = t0;
break;
case AST_TYPE_SIGN:
- n->_type.sign.params = expr;
- n->_type.sign.ret = ret;
+ AST_SIGN_TYPE(n).params = t0;
+ AST_SIGN_TYPE(n).ret = t1;
break;
}
@@ -556,60 +532,45 @@ void destroy_type(struct ast_node *type)
{
assert(type->node_type == AST_TYPE);
switch (type->_type.kind) {
- case AST_TYPE_GENERIC:
- destroy_ast_node(type->_type.generic.id);
- DESTROY_LIST(type->_type.generic.args);
- break;
-
- case AST_TYPE_MEMBER:
- destroy_ast_node(type->_type.member.id);
- destroy_ast_node(type->_type.member.expr);
- break;
-
- case AST_TYPE_ALIAS:
+ case AST_TYPE_PRIMITIVE:
+ destroy_ast_node(AST_PRIMITIVE_TYPE(type).id);
break;
case AST_TYPE_TRAIT:
break;
case AST_TYPE_ID:
- destroy_ast_node(type->_type.id);
+ destroy_ast_node(AST_ID_TYPE(type).id);
break;
case AST_TYPE_ARR:
- destroy_ast_node(type->_type.arr.size);
+ destroy_ast_node(AST_ARR_TYPE(type).size);
+ destroy_ast_node(AST_ARR_TYPE(type).base);
break;
case AST_TYPE_TYPEOF:
- destroy_ast_node(type->_type.typeo.expr);
+ destroy_ast_node(AST_TYPEOF_TYPE(type).expr);
break;
case AST_TYPE_POINTER:
+ destroy_ast_node(AST_PTR_TYPE(type).base);
break;
- case AST_TYPE_PROC:
- DESTROY_LIST(type->_type.proc.params);
- destroy_ast_node(type->_type.proc.ret);
- break;
-
- case AST_TYPE_UNION:
case AST_TYPE_STRUCT:
- destroy_ast_node(type->_type.struc.id);
- DESTROY_LIST(type->_type.struc.impls);
+ destroy_ast_node(AST_STRUCT_TYPE(type).def);
break;
case AST_TYPE_ENUM:
- destroy_ast_node(type->_type.enu.id);
- destroy_ast_node(type->_type.enu.type);
+ destroy_ast_node(AST_ENUM_TYPE(type).def);
break;
case AST_TYPE_SIGN:
- DESTROY_LIST(type->_type.sign.params);
- destroy_ast_node(type->_type.sign.ret);
+ DESTROY_LIST(AST_SIGN_TYPE(type).params);
+ destroy_ast_node(AST_SIGN_TYPE(type).ret);
break;
}
- destroy_ast_node(type->_type.next);
+ destroy_ast_node(AST_TYPE(type).next);
free(type);
}
@@ -1186,9 +1147,9 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_flags(node);
putchar('\n');
- dump_ast(depth + 1, node->_macro.id);
- dump_ast(depth + 1, node->_macro.params);
- dump_ast(depth + 1, node->_macro.body);
+ dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).id);
+ dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).params);
+ dump_ast(depth + 1, AST_MACRO_CONSTRUCT(node).body);
dump(depth, "}\n");
break;
@@ -1270,80 +1231,58 @@ static void __dump_ast(int depth, struct ast_node *node)
dump_flags(node);
switch (node->_type.kind) {
- case AST_TYPE_GENERIC:
- printf(" GENERIC\n");
- dump_ast(depth + 1, node->_type.generic.id);
- dump_ast(depth + 1, node->_type.generic.args);
- break;
-
- case AST_TYPE_MEMBER:
- printf(" MEMBER\n");
- dump_ast(depth + 1, node->_type.member.id);
- dump_ast(depth + 1, node->_type.member.expr);
- break;
-
- case AST_TYPE_ALIAS:
- printf(" ALIAS\n");
- dump_ast(depth + 1, node->_type.alias.alias->_alias.id);
- dump_ast(depth + 1, node->_type.alias.actual);
+ case AST_TYPE_PRIMITIVE:
+ printf(" PRIMITIVE\n");
+ dump_ast(depth + 1, AST_PRIMITIVE_TYPE(node).id);
break;
case AST_TYPE_TRAIT:
printf(" TRAIT\n");
- dump_ast(depth + 1,
- node->_type.trait.trait->_trait.id);
- dump_ast(depth + 1, node->_type.trait.actual);
+ /* might be a bit overkill? */
+ dump_ast(depth + 1, AST_TRAIT_TYPE(node).def);
break;
case AST_TYPE_ID:
printf(" ID\n");
- dump_ast(depth + 1, node->_type.id);
+ dump_ast(depth + 1, AST_ID_TYPE(node).id);
break;
case AST_TYPE_ARR:
printf(" ARR\n");
- dump_ast(depth + 1, node->_type.arr.size);
+ dump_ast(depth + 1, AST_ARR_TYPE(node).size);
+ dump_ast(depth + 1, AST_ARR_TYPE(node).base);
break;
case AST_TYPE_POINTER:
printf(" PTR\n");
+ dump_ast(depth + 1, AST_PTR_TYPE(node).base);
break;
case AST_TYPE_TYPEOF:
printf(" TYPEOF\n");
- dump_ast(depth + 1, node->_type.typeo.expr);
- dump_ast(depth + 1, node->_type.typeo.actual);
- break;
-
- case AST_TYPE_PROC:
- printf(" PROC\n");
- dump_ast(depth + 1, node->_type.proc.params);
- dump_ast(depth + 1, node->_type.proc.ret);
+ dump_ast(depth + 1, AST_TYPEOF_TYPE(node).expr);
break;
- /* not really but y'know */
- case AST_TYPE_UNION:
case AST_TYPE_STRUCT:
printf(" STRUCT\n");
/* oh yeah, struc is at least right now just an ID that
* we can use to fetch the actual struct with. */
- dump_ast(depth + 1, node->_type.struc.id);
- dump_ast(depth + 1, node->_type.struc.impls);
+ dump_ast(depth + 1, AST_STRUCT_TYPE(node).def);
break;
case AST_TYPE_ENUM:
printf(" ENUM\n");
- dump_ast(depth + 1, node->_type.enu.id);
- dump_ast(depth + 1, node->_type.enu.type);
+ dump_ast(depth + 1, AST_ENUM_TYPE(node).def);
break;
- case AST_TYPE_SIGN: printf(" SIGN\n");
- dump_ast(depth + 1, node->_type.sign.params);
- dump_ast(depth + 1, node->_type.sign.ret);
+ case AST_TYPE_SIGN:
+ printf(" SIGN\n");
+ dump_ast(depth + 1, AST_SIGN_TYPE(node).params);
+ dump_ast(depth + 1, AST_SIGN_TYPE(node).ret);
break;
}
- dump_ast(depth + 1, node->_type.next);
+ dump_ast(depth + 1, AST_TYPE(node).next);
dump(depth, "}\n");
break;
@@ -1473,11 +1412,10 @@ static void __dump_ast(int depth, struct ast_node *node)
dump(depth, "{CONST:");
dump_flags(node);
switch (node->_const.kind) {
- case AST_CONST_INTEGER: printf("%lli", node->_const.integer);
+ case AST_CONST_INTEGER: printf(" %lli", AST_CONST(node).integer);
break;
- case AST_CONST_STRING: printf("\"%s\"", node->_const.str);
+ case AST_CONST_STRING: printf(" \"%s\"", AST_CONST(node).str);
break;
- case AST_CONST_FLOAT: printf("%lf", node->_const.dbl); break;
}
printf("}\n");
break;
@@ -1531,21 +1469,24 @@ struct ast_node *clone_ast_node(struct ast_node *node)
struct ast_node *new = NULL;
switch (node->node_type) {
case AST_ARR_ACCESS:
- new = gen_arr_access(clone_ast_node(node->arr_access.base),
- clone_ast_node(node->arr_access.idx),
+ new = gen_arr_access(
+ clone_ast_node(AST_ARR_ACCESS(node).base),
+ clone_ast_node(AST_ARR_ACCESS(node).idx),
node->loc);
break;
case AST_TYPE_CONSTRUCT:
- new = gen_type_construct(clone_ast_node(node->type_construct.id),
- clone_ast_node(node->type_construct.params),
- clone_ast_node(node->type_construct.body),
+ new = gen_type_construct(
+ clone_ast_node(AST_TYPE_CONSTRUCT(node).id),
+ clone_ast_node(AST_TYPE_CONSTRUCT(node).params),
+ clone_ast_node(AST_TYPE_CONSTRUCT(node).body),
node->loc);
break;
case AST_TYPE_EXPAND:
- new = gen_type_expand(clone_ast_node(node->type_expand.id),
- clone_ast_node(node->type_expand.args),
+ new = gen_type_expand(
+ clone_ast_node(AST_TYPE_EXPAND(node).id),
+ clone_ast_node(AST_TYPE_EXPAND(node).args),
node->loc);
break;
@@ -1596,13 +1537,14 @@ struct ast_node *clone_ast_node(struct ast_node *node)
break;
case AST_MACRO_CONSTRUCT: new = gen_macro_construct(
- clone_ast_node(node->_macro.id),
- clone_ast_node(node->_macro.params),
- clone_ast_node(node->_macro.body));
- break;
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).id),
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).params),
+ clone_ast_node(AST_MACRO_CONSTRUCT(node).body));
+ break;
- case AST_MACRO_EXPAND: new = gen_macro_expand(clone_ast_node(node->_macro_expand.id),
- clone_ast_node(node->_macro_expand.args));
+ case AST_MACRO_EXPAND: new = gen_macro_expand(
+ clone_ast_node(AST_MACRO_EXPAND(node).id),
+ clone_ast_node(AST_MACRO_EXPAND(node).args));
break;
case AST_CAST: new = gen_cast(clone_ast_node(node->_cast.expr),
@@ -1652,82 +1594,63 @@ struct ast_node *clone_ast_node(struct ast_node *node)
/* oh, if a node has a ->type it probably isn't cloned
* correctly... */
switch (node->_type.kind) {
- case AST_TYPE_GENERIC:
- new = gen_type(AST_TYPE_GENERIC,
- clone_ast_node(node->_type.generic.id),
- clone_ast_node(node->_type.generic.args),
- NULL);
- break;
-
- case AST_TYPE_MEMBER:
- new = gen_type(AST_TYPE_MEMBER,
- clone_ast_node(node->_type.member.id),
- clone_ast_node(node->_type.member.expr),
- NULL);
- break;
-
- case AST_TYPE_ALIAS:
- new = gen_type(AST_TYPE_ALIAS, NULL,
- /* should make it more obvious what is a
- * reference and what isn't */
- node->_type.alias.alias,
- node->_type.alias.actual);
+ case AST_TYPE_PRIMITIVE:
+ new = gen_type(AST_TYPE_PRIMITIVE,
+ clone_ast_node(AST_PRIMITIVE_TYPE(node).id),
+ NULL,
+ NULL);
break;
case AST_TYPE_TRAIT:
- new = gen_type(AST_TYPE_TRAIT, NULL,
- node->_type.trait.trait,
- /* ditto, should actual be cloned? */
- node->_type.trait.actual);
+ new = gen_type(AST_TYPE_TRAIT,
+ AST_TRAIT_TYPE(node).def,
+ NULL,
+ NULL);
break;
case AST_TYPE_ID:
new = gen_type(AST_TYPE_ID,
- clone_ast_node(node->_type.id),
- NULL, NULL);
+ clone_ast_node(AST_ID_TYPE(node).id),
+ NULL,
+ NULL);
break;
case AST_TYPE_ARR:
- new = gen_type(AST_TYPE_ARR, NULL,
- clone_ast_node(node->_type.arr.size),
- NULL);
+ new = gen_type(AST_TYPE_ARR,
+ clone_ast_node(AST_ARR_TYPE(node).size),
+ clone_ast_node(AST_ARR_TYPE(node).base),
+ NULL);
break;
case AST_TYPE_TYPEOF:
- new = gen_type(AST_TYPE_TYPEOF, NULL,
- clone_ast_node(node->_type.typeo.expr),
+ new = gen_type(AST_TYPE_TYPEOF,
+ clone_ast_node(AST_TYPEOF_TYPE(node).expr),
+ NULL,
NULL);
break;
case AST_TYPE_POINTER:
- new = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
+ new = gen_type(AST_TYPE_POINTER, AST_PTR_TYPE(node).base, NULL, NULL);
break;
- case AST_TYPE_UNION:
case AST_TYPE_STRUCT:
new = gen_type(AST_TYPE_STRUCT,
- clone_ast_node(node->_type.struc.id),
- clone_ast_node(node->_type.struc.impls),
+ clone_ast_node(AST_STRUCT_TYPE(node).def),
+ NULL,
NULL);
break;
case AST_TYPE_ENUM:
new = gen_type(AST_TYPE_ENUM,
- clone_ast_node(node->_type.enu.id),
- clone_ast_node(node->_type.enu.type),
+ clone_ast_node(AST_ENUM_TYPE(node).def),
+ NULL,
NULL);
break;
- case AST_TYPE_PROC:
- new = gen_type(AST_TYPE_PROC, NULL,
- clone_ast_node(node->_type.proc.params),
- clone_ast_node(node->_type.proc.ret));
- break;
-
case AST_TYPE_SIGN:
new = gen_type(AST_TYPE_SIGN, NULL,
- clone_ast_node(node->_type.sign.params),
- clone_ast_node(node->_type.sign.ret));
+ clone_ast_node(AST_SIGN_TYPE(node).params),
+ clone_ast_node(AST_SIGN_TYPE(node).ret));
break;
}
@@ -1953,16 +1876,13 @@ static int identical_defer(int exact, struct ast_node *a, struct ast_node *b)
static int identical_macro_construct(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_macro.id, b->_macro.id))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_macro.params, b->_macro.params))
+ if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).id, AST_MACRO_CONSTRUCT(b).id))
return 0;
- if (!identical_ast_nodes(exact, a->_macro.body, b->_macro.body))
+ if (!identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).params, AST_MACRO_CONSTRUCT(b).params))
return 0;
- return 1;
+ return identical_ast_nodes(exact, AST_MACRO_CONSTRUCT(a).body, AST_MACRO_CONSTRUCT(b).body);
}
static int identical_macro_expand(int exact, struct ast_node *a, struct ast_node *b)
@@ -2043,127 +1963,56 @@ static int identical_return(int exact, struct ast_node *a, struct ast_node *b)
return identical_ast_nodes(exact, a->_return.expr, b->_return.expr);
}
-static int identical_type_alias(int exact, struct ast_node *a,
- struct ast_node *b)
+static int identical_type_id(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.alias.alias,
- b->_type.alias.alias))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.alias.actual,
- b->_type.alias.actual))
- return 0;
- return 1;
+ return identical_ast_nodes(exact, AST_ID_TYPE(a).id, AST_ID_TYPE(b).id);
}
-static int identical_type_trait(int exact, struct ast_node *a,
- struct ast_node *b)
+static int identical_type_arr(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.trait.trait,
- b->_type.trait.trait))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.trait.actual,
- b->_type.trait.actual))
+ if (!identical_ast_nodes(exact, AST_ARR_TYPE(a).size, AST_ARR_TYPE(b).size))
return 0;
- return 1;
+ return identical_ast_nodes(exact, AST_ARR_TYPE(a).base, AST_ARR_TYPE(b).base);
}
-static int identical_type_id(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_type_trait(int exact, struct ast_node *a, struct ast_node *b)
{
- return identical_ast_nodes(exact, a->_type.id, b->_type.id);
+ return identical_ast_nodes(exact, AST_TRAIT_TYPE(a).def, AST_TRAIT_TYPE(b).def);
}
-static int identical_type_arr(int exact, struct ast_node *a, struct ast_node *b)
+static int identical_type_primitive(int exact, struct ast_node *a, struct ast_node *b)
{
- return identical_ast_nodes(exact, a->_type.arr.size, b->_type.arr.size);
+ return identical_ast_nodes(exact, AST_PRIMITIVE_TYPE(a).id, AST_PRIMITIVE_TYPE(b).id);
}
static int identical_type_typeof(int exact, struct ast_node *a,
struct ast_node *b)
{
- return identical_ast_nodes(exact, a->_type.typeo.expr,
- b->_type.typeo.expr);
-}
-
-static int identical_type_proc(int exact, struct ast_node *a,
- struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, a->_type.proc.params,
- b->_type.proc.params))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.proc.ret, b->_type.proc.ret))
- return 0;
-
- return 1;
+ return identical_ast_nodes(exact, AST_TYPEOF_TYPE(a).expr,
+ AST_TYPEOF_TYPE(b).expr);
}
static int identical_type_sign(int exact, struct ast_node *a,
struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.sign.params,
- b->_type.sign.params))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.sign.ret, b->_type.sign.ret))
+ if (!identical_ast_nodes(exact, AST_SIGN_TYPE(a).params,
+ AST_SIGN_TYPE(b).params))
return 0;
- return 1;
+ return identical_ast_nodes(exact, AST_SIGN_TYPE(a).ret, AST_SIGN_TYPE(b).ret);
}
static int identical_type_struct(int exact, struct ast_node *a,
struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.struc.id, b->_type.struc.id))
- return 0;
-
- if (!identical_ast_nodes(1, a->_type.struc.impls,
- b->_type.struc.impls))
- return 0;
-
- return 1;
+ return identical_ast_nodes(exact, AST_STRUCT_TYPE(a).def, AST_STRUCT_TYPE(b).def);
}
static int identical_type_enum(int exact, struct ast_node *a,
struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->_type.enu.id, b->_type.enu.id))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.enu.type, b->_type.enu.type))
- return 0;
-
- return 1;
-}
-
-static int identical_type_member(int exact, struct ast_node *a,
- struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, a->_type.member.id, b->_type.member.id))
- return 0;
-
- if (!identical_ast_nodes(exact, a->_type.member.expr,
- b->_type.member.expr))
- return 0;
-
- return 1;
-}
-
-static int identical_type_generic(int exact, struct ast_node *a,
- struct ast_node *b)
-{
- if (!identical_ast_nodes(exact, a->_type.generic.id,
- b->_type.generic.id))
- return 0;
-
- /* array should always be checked, so do an exact match */
- if (!identical_ast_nodes(1, a->_type.generic.args,
- b->_type.generic.args))
- return 0;
-
- return 1;
+ return identical_ast_nodes(exact, AST_ENUM_TYPE(a).def, AST_ENUM_TYPE(b).def);
}
static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
@@ -2173,18 +2022,13 @@ static int identical_type(int exact, struct ast_node *a, struct ast_node *b)
int ret = 0;
switch (a->_type.kind) {
- case AST_TYPE_GENERIC: ret = identical_type_generic(exact, a, b); break;
- case AST_TYPE_MEMBER: ret = identical_type_member(exact, a, b); break;
+ case AST_TYPE_PRIMITIVE: ret = identical_type_primitive(exact, a, b); break;
case AST_TYPE_ENUM: ret = identical_type_enum(exact, a, b); break;
- case AST_TYPE_ALIAS: ret = identical_type_alias(exact, a, b); break;
- case AST_TYPE_TRAIT: ret = identical_type_trait(exact, a, b);
- break;
+ case AST_TYPE_TRAIT: ret = identical_type_trait(exact, a, b); break;
case AST_TYPE_ID: ret = identical_type_id(exact, a, b); break;
case AST_TYPE_ARR: ret = identical_type_arr(exact, a, b); break;
case AST_TYPE_TYPEOF: ret = identical_type_typeof(exact, a, b); break;
- case AST_TYPE_PROC: ret = identical_type_proc(exact, a, b); break;
case AST_TYPE_SIGN: ret = identical_type_sign(exact, a, b); break;
- case AST_TYPE_UNION:
case AST_TYPE_STRUCT: ret = identical_type_struct(exact, a, b); break;
case AST_TYPE_POINTER: break;
}
@@ -2361,35 +2205,29 @@ static int identical_fetch(int exact, struct ast_node *a, struct ast_node *b)
static int identical_type_expand(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->type_expand.id, b->type_expand.id))
- return 0;
-
- if (!identical_ast_nodes(exact, a->type_expand.args, b->type_expand.args))
+ if (!identical_ast_nodes(exact, AST_TYPE_EXPAND(a).id, AST_TYPE_EXPAND(b).id))
return 0;
- return 1;
+ return identical_ast_nodes(exact, AST_TYPE_EXPAND(a).args, AST_TYPE_EXPAND(b).args);
}
static int identical_type_construct(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->type_construct.id, b->type_construct.id))
+ if (!identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).id, AST_TYPE_CONSTRUCT(b).id))
return 0;
- if (!identical_ast_nodes(exact, a->type_construct.params, b->type_construct.params))
+ if (!identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).params, AST_TYPE_CONSTRUCT(b).params))
return 0;
- if (!identical_ast_nodes(exact, a->type_construct.body, b->type_construct.body))
- return 0;
-
- return 1;
+ return identical_ast_nodes(exact, AST_TYPE_CONSTRUCT(a).body, AST_TYPE_CONSTRUCT(b).body);
}
static int identical_arr_access(int exact, struct ast_node *a, struct ast_node *b)
{
- if (!identical_ast_nodes(exact, a->arr_access.base, b->arr_access.base))
+ if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).base, AST_ARR_ACCESS(b).base))
return 0;
- if (!identical_ast_nodes(exact, a->arr_access.idx, b->arr_access.idx))
+ if (!identical_ast_nodes(exact, AST_ARR_ACCESS(a).idx, AST_ARR_ACCESS(b).idx))
return 0;
return 1;
@@ -2648,58 +2486,37 @@ static int call_on_case(int (*call)(struct ast_node *,
return ret;
}
-static int call_on_type_alias(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_type.alias.alias, data);
- ret |= call(node->_type.alias.actual, data);
- return ret;
-}
-
static int call_on_type_trait(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.trait.trait, data);
- ret |= call(node->_type.trait.actual, data);
+ ret |= call(AST_TRAIT_TYPE(node).def, data);
return ret;
}
static int call_on_type_id(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
- return call(node->_type.id, data);
+ return call(AST_ID_TYPE(node).id, data);
}
static int call_on_type_arr(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
- return call(node->_type.arr.size, data);
+ return call(AST_ARR_TYPE(node).size, data);
}
static int call_on_type_typeof(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
- return call(node->_type.typeo.expr, data);
+ return call(AST_TYPEOF_TYPE(node).expr, data);
}
static int call_on_type_struct(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.struc.id, data);
- ret |= call(node->_type.struc.impls, data);
- return ret;
-}
-
-static int call_on_type_proc(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_type.proc.id, data);
- ret |= call(node->_type.proc.params, data);
- ret |= call(node->_type.proc.ret, data);
+ ret |= call(AST_STRUCT_TYPE(node).def, data);
return ret;
}
@@ -2707,8 +2524,8 @@ static int call_on_type_sign(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.sign.params, data);
- ret |= call(node->_type.sign.ret, data);
+ ret |= call(AST_SIGN_TYPE(node).params, data);
+ ret |= call(AST_SIGN_TYPE(node).ret, data);
return ret;
}
@@ -2716,26 +2533,15 @@ static int call_on_type_enum(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.enu.id, data);
- ret |= call(node->_type.enu.type, data);
+ ret |= call(AST_ENUM_TYPE(node).def, data);
return ret;
}
-static int call_on_type_member(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
+static int call_on_type_primitive(int (*call)(struct ast_node *, void *),
+ struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_type.member.id, data);
- ret |= call(node->_type.member.expr, data);
- return ret;
-}
-
-static int call_on_type_generic(int (*call)(struct ast_node *,
- void *), struct ast_node *node, void *data)
-{
- int ret = 0;
- ret |= call(node->_type.generic.id, data);
- ret |= call(node->_type.generic.args, data);
+ ret |= call(AST_PRIMITIVE_TYPE(node).id, data);
return ret;
}
@@ -2744,23 +2550,13 @@ static int call_on_type(int (*call)(struct ast_node *,
{
int ret = 0;
switch (node->_type.kind) {
- case AST_TYPE_GENERIC: ret = call_on_type_generic(call, node, data);
- break;
- case AST_TYPE_MEMBER: ret = call_on_type_member(call, node, data);
- break;
+ case AST_TYPE_PRIMITIVE: ret = call_on_type_primitive(call, node, data); break;
case AST_TYPE_ENUM: ret = call_on_type_enum(call, node, data); break;
- case AST_TYPE_ALIAS: ret = call_on_type_alias(call, node, data); break;
- case AST_TYPE_TRAIT: ret = call_on_type_trait(call, node, data);
- break;
+ case AST_TYPE_TRAIT: ret = call_on_type_trait(call, node, data); break;
case AST_TYPE_ID: ret = call_on_type_id(call, node, data); break;
case AST_TYPE_ARR: ret = call_on_type_arr(call, node, data); break;
- case AST_TYPE_TYPEOF: ret = call_on_type_typeof(call, node, data);
- break;
- case AST_TYPE_UNION:
- case AST_TYPE_STRUCT: ret = call_on_type_struct(call, node, data);
- break;
- case AST_TYPE_PROC: ret = call_on_type_proc(call, node, data); break;
- break;
+ case AST_TYPE_TYPEOF: ret = call_on_type_typeof(call, node, data); break;
+ case AST_TYPE_STRUCT: ret = call_on_type_struct(call, node, data); break;
case AST_TYPE_SIGN: ret = call_on_type_sign(call, node, data); break;
case AST_TYPE_POINTER: break;
}
@@ -2808,9 +2604,9 @@ static int call_on_macro_construct(int (*call)(struct ast_node *,
void *), struct ast_node *node, void *data)
{
int ret = 0;
- ret |= call(node->_macro.id, data);
- ret |= call(node->_macro.params, data);
- ret |= call(node->_macro.body, data);
+ ret |= call(AST_MACRO_CONSTRUCT(node).id, data);
+ ret |= call(AST_MACRO_CONSTRUCT(node).params, data);
+ ret |= call(AST_MACRO_CONSTRUCT(node).body, data);
return ret;
}
@@ -2850,17 +2646,18 @@ static int call_on_macro_expand(int (*call)(struct ast_node *, void *), struct a
static int call_on_type_construct(int (*call)(struct ast_node *, void *), struct ast_node *type_construct, void *data)
{
int ret = 0;
- ret |= call(AST_GET(type_construct, id), data);
- ret |= call(AST_GET(type_construct, params), data);
- ret |= call(AST_GET(type_construct, body), data);
+ /* pretty verbose, hmm */
+ ret |= call(AST_TYPE_CONSTRUCT(type_construct).id, data);
+ ret |= call(AST_TYPE_CONSTRUCT(type_construct).params, data);
+ ret |= call(AST_TYPE_CONSTRUCT(type_construct).body, data);
return ret;
}
static int call_on_type_expand(int (*call)(struct ast_node *, void *), struct ast_node *type_expand, void *data)
{
int ret = 0;
- ret |= call(AST_GET(type_expand, id), data);
- ret |= call(AST_GET(type_expand, args), data);
+ ret |= call(AST_TYPE_EXPAND(type_expand).id, data);
+ ret |= call(AST_TYPE_EXPAND(type_expand).args, data);
return ret;
}
diff --git a/src/debug.c b/src/debug.c
index 2b993bf..f145234 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -198,84 +198,41 @@ static void _type_str(FILE *fp, struct ast_node *type)
break;
case AST_TYPE_ID: {
- struct ast_node *id = type->_type.id;
- fprintf(fp, "%s", id->_id.id);
+ struct ast_node *id = AST_ID_TYPE(type).id;
+ fprintf(fp, "%s", AST_ID(id).id);
break;
}
case AST_TYPE_TRAIT: {
- struct ast_node *trait = type->_type.trait.trait;
- assert(trait);
-
- struct ast_node *trait_id = trait->_trait.id;
- struct ast_node *trait_act = type->_type.trait.actual;
- if (trait_act) {
- fprintf(fp, "%s as ", trait_id->_id.id);
- _type_str(fp, trait_act);
- }
- else {
- fprintf(fp, "%s", trait_id->_id.id);
- }
- break;
- }
-
- case AST_TYPE_ALIAS: {
- struct ast_node *alias = type->_type.alias.alias;
- assert(alias);
-
- struct ast_node *alias_id = alias->_alias.id;
- struct ast_node *alias_act = type->_type.alias.actual;
- if (alias_act) {
- /* deeply nested aliases look pretty funny here */
- fprintf(fp, "%s aka ", alias_id->_id.id);
- _type_str(fp, alias_act);
- }
- else {
- fprintf(fp, "%s", alias_id->_id.id);
+ struct ast_node *def = AST_TRAIT_TYPE(type).def;
+ if (AST_TRAIT(def).id) {
+ struct ast_node *name = AST_TRAIT(def).id;
+ fprintf(fp, "%s ", AST_ID(name).id);
}
+ fprintf(fp, "(trait)");
break;
}
case AST_TYPE_STRUCT: {
- struct ast_node *struc_id = type->_type.struc.id;
- fprintf(fp, "%s", struc_id->_id.id);
-
- struct ast_node *impls = type->_type.struc.impls;
- if (impls) {
- fprintf(fp, "(");
- while (impls) {
- _type_str(fp, impls);
- impls = impls->next;
- if (impls)
- fprintf(fp, ", ");
- }
- fprintf(fp, ")");
+ struct ast_node *def = AST_STRUCT_TYPE(type).def;
+ if (AST_STRUCT(def).id) {
+ struct ast_node *name = AST_STRUCT(def).id;
+ fprintf(fp, "%s ", AST_ID(name).id);
}
+ fprintf(fp, "(struct)");
+ /** @todo print out anonymous structs with members? */
break;
}
- case AST_TYPE_UNION: {
- struct ast_node *unio_id = type->_type.unio.id;
- fprintf(fp, "%s", unio_id->_id.id);
-
- struct ast_node *impls = type->_type.unio.impls;
- if (impls) {
- fprintf(fp, "(");
- while (impls) {
- _type_str(fp, impls);
- impls = impls->next;
- if (impls)
- fprintf(fp, ", ");
- }
- fprintf(fp, ")");
- }
+ case AST_TYPE_TYPEOF: {
+ fprintf(fp, "(typeof)");
break;
}
- case AST_TYPE_TYPEOF: {
- _type_str(fp, type->_type.typeo.actual);
- fprintf(fp, " (typeof)");
- break;
+ case AST_TYPE_PRIMITIVE: {
+ struct ast_node *id = AST_PRIMITIVE_TYPE(type).id;
+ fprintf(fp, "%s", AST_ID(id).id);
+ break;
}
default:
diff --git a/src/parser.y b/src/parser.y
index 236a106..6975041 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -570,23 +570,17 @@ type
| "^" func_sign {
/* still not entirely sold on this signature, but it's not terrible I
* guess */
- $$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
- $$->_type.next = $2;
+ $$ = gen_type(AST_TYPE_POINTER, $2, NULL, NULL);
}
| "*" type {
- $$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL);
- $$->_type.next = $2;
+ $$ = gen_type(AST_TYPE_POINTER, $2, NULL, NULL);
}
| "[" const_expr "]" type {
- $$ = gen_type(AST_TYPE_ARR, NULL, $2, NULL);
- $$->_type.next = $4;
+ $$ = gen_type(AST_TYPE_ARR, $2, $4, NULL);
}
| "typeof" expr {
$$ = gen_type(AST_TYPE_TYPEOF, NULL, $2, NULL);
}
- | id "::" type {
- $$ = gen_type(AST_TYPE_MEMBER, $1, $3, NULL);
- }
| "const" type {
$$ = $2;
}
diff --git a/src/scope.c b/src/scope.c
index d6481c3..2b8ef12 100644
--- a/src/scope.c
+++ b/src/scope.c
@@ -24,88 +24,53 @@ static struct ast_node *match_proc(struct scope *scope,
static struct ast_node *match_macro(struct scope *scope,
struct ast_node *id, struct ast_node *args);
-static int generics_trait_type(struct ast_node *generics)
+static struct param_node *find_matching_param(struct resolve_node *node,
+ struct ast_node *type)
{
- if (!generics)
- return 0;
+ struct param_node *param = node->params;
+ while (param) {
+ if (types_match(type, param->type))
+ return param;
- if (actual_type(generics)->_type.kind == AST_TYPE_TRAIT)
- return 1;
+ param = param->next;
+ }
- return generics_trait_type(generics->_type.next);
+ return NULL;
}
-static int generic_type(struct ast_node *type)
+static int traits_resolve(struct ast_node *arg_type, struct ast_node *param_type)
{
- if (!type)
- return 0;
-
- if (type->_type.kind == AST_TYPE_STRUCT)
- return generics_trait_type(type->_type.struc.impls);
-
- if (type->_type.kind == AST_TYPE_TRAIT)
- return type->_type.trait.actual == NULL;
-
- return generic_type(type->_type.next);
+ /** @todo are more checks required? */
+ return AST_TYPE(arg_type).as == AST_TRAIT_TYPE(param_type).def;
}
-static int referential_type(struct ast_node *type)
+static int typeofs_resolve(struct ast_node *arg_type, struct ast_node *param_type)
{
- if (!type)
- return 0;
-
- if (type->_type.kind == AST_TYPE_TYPEOF)
- return 1;
-
- if (type->_type.kind == AST_TYPE_MEMBER)
- return 1;
-
- return referential_type(type->_type.next);
-}
-
-int primitive_type(struct ast_node *type)
-{
- if (!type)
- return 1;
-
- if (referential_type(type))
- return 0;
-
- if (generic_type(type))
- return 0;
-
- return 1;
+ internal_error("typeof resolve unimplemented");
+ return 0;
}
-int fully_qualified(struct ast_node *type)
+static int types_resolve(struct ast_node *arg_type, struct ast_node *param_type)
{
- if (!type)
+ /* untyped resolves all */
+ if (!param_type)
return 1;
- assert(type->_type.kind != AST_TYPE_TRAIT);
- if (type->_type.kind == AST_TYPE_STRUCT) {
- if (!ast_flags(type, AST_FLAG_GENERIC))
- return 1;
-
- if (type->_type.struc.impls)
- return fully_qualified(type->_type.struc.impls);
+ if (AST_TYPE(param_type).kind == AST_TYPE_TRAIT)
+ return traits_resolve(arg_type, param_type);
- return 0;
- }
+ if (AST_TYPE(param_type).kind == AST_TYPE_TYPEOF)
+ return typeofs_resolve(arg_type, param_type);
- return fully_qualified(type->_type.next);
+ return types_match(arg_type, param_type);
}
-static struct param_node *find_matching_param(struct resolve_node *node,
- struct ast_node *type)
+static struct param_node *find_resolving_param(struct resolve_node *node,
+ struct ast_node *type)
{
struct param_node *param = node->params;
while (param) {
- /* untyped matches everything, yay */
- if (!param->type)
- return param;
-
- if (types_match(type, param->type))
+ if (types_resolve(type, param->type))
return param;
param = param->next;
@@ -181,12 +146,9 @@ static int add_next_resolve(struct scope *scope, struct ast_node *resolve,
static int add_resolve(struct scope *scope, struct resolve *resolve,
struct ast_node *proc)
{
- struct ast_node *sign = proc->_proc.sign;
- struct ast_node *params = sign->_type.sign.params;
-
- struct scope *resolv_scope = create_scope();
- scope_add_scope(scope, resolv_scope);
- return add_next_resolve(resolv_scope, proc, resolve->root, params);
+ struct ast_node *sign = AST_PROC(proc).sign;
+ struct ast_node *params = AST_SIGN_TYPE(sign).params;
+ return add_next_resolve(scope, proc, resolve->root, params);
}
static struct ast_node *resolve(struct scope *scope,
@@ -194,6 +156,7 @@ static struct ast_node *resolve(struct scope *scope,
struct ast_node *args)
{
assert(node);
+ /* check for no parameters case */
if (!args) {
if (node->resolved)
return node->resolved;
@@ -201,20 +164,18 @@ static struct ast_node *resolve(struct scope *scope,
return NULL;
}
- /* first check if we match a primitive type */
- struct param_node *found = find_matching_param(node, args->type);
+ struct param_node *found = find_resolving_param(node, args->type);
if (found)
return resolve(scope, found->resolved, args->next);
return NULL;
}
-/* if I ever try making the parser multithreaded, this should be atomic. */
-static size_t counter = 0;
struct scope *create_scope()
{
- /* TODO: add in a scope counter, might make things easier to see in the
- * AST dump */
+ /* if I ever try making the parser multithreaded, this should be atomic. */
+ static size_t counter = 0;
+
struct scope *scope = calloc(1, sizeof(struct scope));
if (!scope) {
internal_error("ran out of memory allocating scope");
@@ -242,22 +203,7 @@ void destroy_visible(struct scope *scope, struct visible *visible)
if (prev)
do {
cur = prev->next;
- /* file scope actually owns all the AST nodes, so don't
- * try to destroy them in lower level scopes */
- if (scope_flags(scope, SCOPE_FILE))
- if (prev->owner == scope)
- destroy_ast_node(prev->node);
- free(prev);
- } while ((prev = cur));
-}
-
-static void destroy_scratch(struct scratch *scratch)
-{
- struct scratch *prev = scratch, *cur;
- if (prev)
- do {
- cur = prev->next;
- destroy_ast_node(prev->node);
+ /* destroy AST nodes globally somewhere? */
free(prev);
} while ((prev = cur));
}
@@ -268,7 +214,6 @@ void destroy_actuals(struct actual *actuals)
if (prev)
do {
cur = prev->next;
- destroy_ast_node(prev->node);
free(prev);
} while ((prev = cur));
}
@@ -301,7 +246,6 @@ void destroy_resolve(struct resolve *resolve)
do {
cur = prev->next;
destroy_resolve_node(prev->root);
- destroy_ast_node(prev->id);
free(prev);
} while ((prev = cur));
}
@@ -317,19 +261,12 @@ void destroy_scope(struct scope *scope)
free((void *)scope->fctx.fname);
}
- destroy_scratch(scope->scratch);
destroy_resolve(scope->proc_resolve);
destroy_resolve(scope->macro_resolve);
destroy_resolve(scope->type_construct_resolve);
destroy_visible(scope, scope->vars);
- destroy_visible(scope, scope->procs);
- destroy_visible(scope, scope->builtins);
-
- destroy_visible(scope, scope->enums);
- destroy_visible(scope, scope->structs);
- destroy_visible(scope, scope->aliases);
- destroy_visible(scope, scope->traits);
+ destroy_visible(scope, scope->types);
struct scope *prev = scope->children, *cur;
if (prev)
@@ -353,247 +290,71 @@ int scope_flags(struct scope *scope, enum scope_flags flags)
return scope->flags & flags;
}
-static struct visible *create_visible(struct scope *owner,
+static struct visible *create_visible(struct ast_node *id,
struct ast_node *node)
{
struct visible *visible = calloc(1, sizeof(struct visible));
+ visible->id = id;
visible->node = node;
- visible->owner = owner;
return visible;
}
-static struct scratch *create_scratch(struct ast_node *scratch)
+struct visible *create_type(struct scope *scope, struct ast_node *id, struct ast_node *type)
{
- struct scratch *new = calloc(1, sizeof(struct scratch));
- new->node = scratch;
- return new;
-}
-
-/* set newest member as head of linked list */
-#define CREATE_VISIBLE(name, type, ast_type) \
- static struct visible *name(struct scope *owner, struct ast_node *node) \
- { \
- assert(node->node_type == ast_type); \
- struct visible *visible = create_visible(owner, node); \
- visible->next = owner->type; \
- owner->type = visible; \
- return visible; \
- }
-
-CREATE_VISIBLE(create_var, vars, AST_VAR);
-CREATE_VISIBLE(create_proc, procs, AST_PROC);
-CREATE_VISIBLE(create_macro, macros, AST_MACRO_CONSTRUCT);
-CREATE_VISIBLE(create_type_construct, type_constructs, AST_TYPE_CONSTRUCT);
-
-CREATE_VISIBLE(create_enum, enums, AST_ENUM);
-CREATE_VISIBLE(create_alias, aliases, AST_ALIAS);
-CREATE_VISIBLE(create_struct, structs, AST_STRUCT);
-CREATE_VISIBLE(create_builtin, builtins, AST_TYPE);
-CREATE_VISIBLE(create_trait, traits, AST_TRAIT);
-
-/* TODO: check for identical names in the scope? */
-#define REFERENCE_VISIBLE(name, list, ast_type) \
- static int name(int public, struct scope *scope, struct visible *obj) \
- { \
- if (!scope) \
- return 0; \
- assert(obj->node->node_type == ast_type); \
- struct visible *ref = create_visible(obj->owner, obj->node); \
- ref->next = scope->list; \
- scope->list = ref; \
- if (scope_flags(scope, SCOPE_FILE) && public) \
- name(scope_flags(scope, SCOPE_PUBLIC), scope->parent, obj); \
- return 0; \
- }
-
-REFERENCE_VISIBLE(reference_var, vars, AST_VAR);
-REFERENCE_VISIBLE(reference_proc, procs, AST_PROC);
-REFERENCE_VISIBLE(reference_macro, macros, AST_MACRO_CONSTRUCT);
-
-REFERENCE_VISIBLE(reference_enum, enums, AST_ENUM);
-REFERENCE_VISIBLE(reference_trait, traits, AST_TRAIT);
-REFERENCE_VISIBLE(reference_alias, aliases, AST_ALIAS);
-REFERENCE_VISIBLE(reference_struct, structs, AST_STRUCT);
-REFERENCE_VISIBLE(reference_builtin, builtins, AST_TYPE);
-REFERENCE_VISIBLE(reference_type_construct, type_constructs, AST_TYPE_CONSTRUCT);
-
-/* does NOT walk the scope tree upward if it doesn't find the var in the scope
- * */
-#define FIND_VISIBLE(name, list, ast_type, ast_name) \
- struct ast_node *name(struct scope *scope, struct ast_node *id) \
- { \
- assert(id->node_type == AST_ID); \
- struct visible *prev = scope->list, *cur; \
- if (prev) { \
- do { \
- cur = prev->next; \
- if (identical_ast_nodes(0, \
- prev->node->ast_name.id, \
- id)) { \
- return prev->node; \
- } \
- } while ((prev = cur)); \
- } \
- return NULL; \
- }
-
-FIND_VISIBLE(scope_find_enum, enums, AST_ENUM, _enum);
-FIND_VISIBLE(scope_find_alias, aliases, AST_ALIAS, _alias);
-FIND_VISIBLE(scope_find_builtin, builtins, AST_TYPE, _type);
-FIND_VISIBLE(scope_find_struct, structs, AST_STRUCT, _struct);
-FIND_VISIBLE(scope_find_trait, traits, AST_TRAIT, _trait);
-/* note that these return the first match for the ID, and as such might not be
- * what should be called. */
-FIND_VISIBLE(scope_find_var, vars, AST_VAR, _var);
-FIND_VISIBLE(scope_find_proc, procs, AST_PROC, _proc);
-FIND_VISIBLE(scope_find_macro, macros, AST_MACRO_CONSTRUCT, _macro);
-FIND_VISIBLE(scope_find_type_construct, type_constructs, AST_TYPE_CONSTRUCT, type_construct);
-
-struct ast_node *scope_find(struct scope *scope, struct ast_node *id)
-{
- assert(id->node_type == AST_ID);
-
- struct ast_node *found = scope_find_var(scope, id);
- if (found)
- return found;
-
- found = scope_find_proc(scope, id);
- if (found)
- return found;
-
- found = scope_find_macro(scope, id);
- if (found)
- return found;
-
- found = scope_find_alias(scope, id);
- if (found)
- return found;
-
- found = scope_find_trait(scope, id);
- if (found)
- return found;
+ struct visible *n = create_visible(id, type);
+ if (!n)
+ return NULL;
- return NULL;
+ n->next = scope->types;
+ scope->types = n;
+ return n;
}
-/* procedure adding requires a bit of tweaking, as a different number of
- * arguments effectively means different functions, not just the name */
-#define ADD_VISIBLE(name, obj_type, ast_type, ast_name) \
- int name(struct scope *scope, struct ast_node *node) \
- { \
- assert(node->node_type == ast_type); \
- struct ast_node *shadow = file_scope_find_##obj_type(scope, \
- node->ast_name.id); \
- if (shadow) { \
- semantic_error(scope->fctx, node, \
- "shadowing is not allowed"); \
- semantic_info(scope->fctx, shadow, \
- "previous declaration was here"); \
- return -1; \
- } \
- int public = scope_flags(scope, SCOPE_PUBLIC); \
- struct visible *visible = create_##obj_type(scope, node); \
- if (scope_flags(scope, \
- SCOPE_FILE) && ast_flags(node, AST_FLAG_PUBLIC)) \
- return reference_##obj_type(public, scope->parent, visible); \
- return 0; \
- }
-
-struct visible *create_type(struct scope *scope, struct ast_node *type)
+struct visible *create_var(struct scope *scope, struct ast_node *id, struct ast_node *var)
{
- switch (type->node_type) {
- case AST_TYPE: return create_builtin(scope, type);
- case AST_ALIAS: return create_alias(scope, type);
- case AST_TRAIT: return create_trait(scope, type);
- case AST_ENUM: return create_enum(scope, type);
- case AST_STRUCT: return create_struct(scope, type);
- default:
- semantic_error(scope->fctx, type, "unknown type");
+ struct visible *n = create_visible(id, var);
+ if (!n)
return NULL;
- }
+
+ n->next = scope->vars;
+ scope->vars = n;
+ return n;
}
-int reference_type(int public, struct scope *scope, struct visible *visible)
+int scope_add_var(struct scope *scope, struct ast_node *var)
{
- switch (visible->node->node_type) {
- case AST_TYPE: return reference_builtin(public, scope, visible);
- case AST_ALIAS: return reference_alias(public, scope, visible);
- case AST_TRAIT: return reference_trait(public, scope, visible);
- case AST_ENUM: return reference_enum(public, scope, visible);
- case AST_STRUCT: return reference_struct(public, scope, visible);
- default:
- semantic_error(scope->fctx, visible->node, "unknown type");
- return 1;
+ struct ast_node *exists = file_scope_find_var(scope, AST_VAR(var).id);
+ if (exists) {
+ semantic_error(scope->fctx, var, "var redefined");
+ semantic_info(scope->fctx, exists, "previously here");
+ return -1;
}
+
+ struct visible *visible = create_var(scope, AST_VAR(var).id, var);
+ if (scope_flags(scope, SCOPE_FILE) && ast_flags(var, AST_FLAG_PUBLIC))
+ return scope_add_var(scope->parent, var);
+
+ return 0;
}
-int scope_add_type(struct scope *scope, struct ast_node *type)
+int scope_add_type(struct scope *scope, struct ast_node *id, struct ast_node *type)
{
- struct ast_node *exists = file_scope_resolve_type(scope, type);
-
+ struct ast_node *exists = file_scope_find_type(scope, id);
/* redefining a type to itself is allowed, and might be necessary for
* some generics operations. I'll have to double check this later,
* though */
- /* e.g. struct (vec{t}) or something, all instances of this 'type'
- * detected anywhere should be allowed to be 'added' */
- if (exists)
- return 0;
+ if (exists) {
+ semantic_error(scope->fctx, type, "type redefined");
+ semantic_info(scope->fctx, exists, "previously here");
+ return -1;
+ }
- int public = scope_flags(scope, SCOPE_PUBLIC);
/* during a redefine, if it's redefined to public should it be
* propagated upward? Probably not, but dunno for sure yet */
- struct visible *visible = create_type(scope, type);
+ struct visible *visible = create_type(scope, id, type);
if (scope_flags(scope, SCOPE_FILE) && ast_flags(type, AST_FLAG_PUBLIC))
- return reference_type(public, scope->parent, visible);
-
- return 0;
-}
-
-struct ast_node *scope_find_type(struct scope *scope, struct ast_node *id)
-{
- assert(id->node_type == AST_ID);
-
- struct ast_node *found = scope_find_builtin(scope, id);
- if (found)
- return found;
-
- found = scope_find_enum(scope, id);
- if (found)
- return found;
-
- found = scope_find_struct(scope, id);
- if (found)
- return found;
-
- found = scope_find_alias(scope, id);
- if (found)
- return found;
-
- found = scope_find_trait(scope, id);
- if (found)
- return found;
-
- return NULL;
-}
-
-ADD_VISIBLE(scope_add_var, var, AST_VAR, _var);
-ADD_VISIBLE(scope_add_alias, alias, AST_ALIAS, _alias);
-ADD_VISIBLE(scope_add_trait, trait, AST_TRAIT, _trait);
-
-static int add_implementation(struct ast_node *trait, struct ast_node *type)
-{
- assert(
- trait->node_type == AST_TRAIT &&
- type->node_type == AST_TYPE);
- struct trait_implemented *by = calloc(1, sizeof(*type));
- if (!by) {
- internal_error("failed allocating memory for implementation");
- return 1;
- }
+ return scope_add_type(scope->parent, id, type);
- by->type = type;
- by->next = trait->_trait.impl_by;
- trait->_trait.impl_by = by;
return 0;
}
@@ -617,81 +378,17 @@ static void remove_implementation(struct ast_node *trait,
} while ((prev = cur));
}
-static int find_implementation(struct ast_node *trait, struct ast_node *type)
-{
- if (!type)
- return 0;
-
- assert(trait->node_type == AST_TRAIT);
- if (type->_type.kind == AST_TYPE_TRAIT)
- return find_implementation(trait,
- type->_type.trait.actual);
-
- if (type->_type.kind == AST_TYPE_ALIAS)
- return find_implementation(trait, type->_type.alias.actual);
-
- /* I'm not 100% sold on having to handle these special cases multiple
- * times in different places, but I'm not sure what alternatives I have.
- * For debugging purposes, maintaining as much info about the original
- * code is useful, but I wonder if I can somehow maybe clone this stuff
- * and keep a reference to the original or something without too much
- * work? TODO */
- if (type->_type.kind == AST_TYPE_TYPEOF)
- return find_implementation(trait, type->_type.typeo.actual);
-
- struct trait_implemented *prev = trait->_trait.impl_by, *cur;
- if (prev)
- do {
- cur = prev->next;
- if (identical_ast_nodes(0, prev->type, type)) {
- return 1;
- }
- } while ((prev = cur));
-
- return 0;
-}
-
static int implements_proc(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type,
struct ast_node *param_type, struct ast_node *proc)
{
+ (void)(flags);
+ (void)(scope);
+ (void)(arg_type);
+ (void)(param_type);
assert(proc->node_type == AST_PROC);
- /* temp */
- struct ast_node *id = proc->_proc.id;
- /* this removes type info, bit of an issue */
- struct ast_node *sign = clone_ast_node(proc->_proc.sign);
- struct ast_node *params = sign->_type.sign.params;
- struct ast_node *ret = sign->_type.sign.ret;
-
- init_trait_types(params, param_type, arg_type);
- init_trait_type(ret, param_type, arg_type);
-
- struct ast_node *impl = match_proc(scope, id, params);
- if (!impl)
- goto out;
-
- struct ast_node *impl_ret = impl->_proc.sign->_type.sign.ret;
- /* note important distinction between when to use ->type and when to not
- * in short: ->type can be a trait or alias, not using it is the type
- * before being resolved.
- */
- /* TODO: detect loops, such as when two trait return params rely on
- * eachother */
- if (!implements(flags, scope, impl_ret, ret)) {
- char *irt = type_str(impl_ret);
- char *prt = type_str(ret);
- semantic_error(scope->fctx, proc, "return type mismatch");
- semantic_info(scope->fctx, impl,
- "found return type %s, expected %s",
- irt, prt);
- free(irt);
- free(prt);
- impl = NULL;
- }
-
-out:
- destroy_ast_node(sign);
- return impl != NULL;
+ /** @todo implement */
+ return 0;
}
static int implements_var(enum match_flags flags, struct scope *scope,
@@ -703,7 +400,7 @@ static int implements_var(enum match_flags flags, struct scope *scope,
(void)(arg_type);
(void)(param_type);
assert(var->node_type == AST_VAR);
- /* temp */
+ /** @todo implement */
return 0;
}
@@ -711,66 +408,53 @@ static int implements_trait(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type,
struct ast_node *param_type)
{
- assert(param_type->_type.kind == AST_TYPE_TRAIT);
- if (param_type->_type.trait.actual)
- return implements(flags, scope, arg_type,
- param_type->_type.trait.actual);
-
- struct ast_node *trait = param_type->_type.trait.trait;
- /* if we already know we implement this trait, nothing to do */
- if (find_implementation(trait, arg_type))
- return 1;
-
- /* optimistically assume we implement type trait */
- /* TODO: this optimism might be questionable, as some trait might rely
- * on another trait being implemented by the same type.
- * The other type will return an error message, and the compilation will
- * fail, but the error messages generated might be misleading. Look into
- * it at some point. */
- add_implementation(trait, arg_type);
-
- struct ast_node *body = trait->_trait.body;
+ assert(AST_TYPE(param_type).kind == AST_TYPE_TRAIT);
+ struct ast_node *trait = AST_TRAIT_TYPE(param_type).def;
+ struct ast_node *body = AST_TRAIT(trait).body;
/* if the body is empty, match */
struct ast_node *elem = body;
- if (elem)
- do {
- if (elem->node_type == AST_VAR) {
- if (implements_var(flags, scope, arg_type,
- param_type,
- elem))
- continue;
+ if (!elem)
+ return 1;
- char *type = type_str(arg_type);
- struct ast_node *id = elem->_proc.id;
- semantic_error(scope->fctx, elem,
- "%s does not have member %s",
- type, id->_id.id);
- free(type);
- goto not_implemented;
- }
+ /* this is somewhat ugly, hmmm */
+ do {
+ if (elem->node_type == AST_VAR) {
+ if (implements_var(flags, scope, arg_type,
+ param_type,
+ elem))
+ continue;
- else if (elem->node_type == AST_PROC) {
- if (implements_proc(flags, scope, arg_type,
- param_type,
- elem))
- continue;
+ char *type = type_str(arg_type);
+ struct ast_node *id = elem->_proc.id;
+ semantic_error(scope->fctx, elem,
+ "%s does not have member %s",
+ type, id->_id.id);
+ free(type);
+ goto not_implemented;
+ }
- char *type = type_str(arg_type);
- struct ast_node *id = elem->_proc.id;
- semantic_error(scope->fctx, elem,
- "%s does not implement %s",
- type, id->_id.id);
- free(type);
- goto not_implemented;
- }
+ else if (elem->node_type == AST_PROC) {
+ if (implements_proc(flags, scope, arg_type,
+ param_type,
+ elem))
+ continue;
- else {
- semantic_error(scope->fctx, elem,
- "illegal trait element");
- goto not_implemented;
- }
- } while ((elem = elem->next));
+ char *type = type_str(arg_type);
+ struct ast_node *id = elem->_proc.id;
+ semantic_error(scope->fctx, elem,
+ "%s does not implement %s",
+ type, id->_id.id);
+ free(type);
+ goto not_implemented;
+ }
+
+ else {
+ semantic_error(scope->fctx, elem,
+ "illegal trait element");
+ goto not_implemented;
+ }
+ } while ((elem = elem->next));
return 1;
@@ -779,29 +463,11 @@ not_implemented:
return 0;
}
-static int implements_alias(enum match_flags flags, struct scope *scope,
- struct ast_node *arg_type,
- struct ast_node *param_type)
-{
- while (arg_type && arg_type->_type.kind == AST_TYPE_ALIAS)
- arg_type = arg_type->_type.alias.actual;
-
- while (param_type && param_type->_type.kind == AST_TYPE_ALIAS)
- param_type = param_type->_type.alias.actual;
-
- return implements(flags, scope, arg_type, param_type);
-}
-
static int implements_typeof(enum match_flags flags, struct scope *scope,
struct ast_node *arg_type,
struct ast_node *param_type)
{
- while (arg_type && arg_type->_type.kind == AST_TYPE_TYPEOF)
- arg_type = arg_type->_type.typeo.actual;
-
- while (param_type && param_type->_type.kind == AST_TYPE_TYPEOF)
- param_type = param_type->_type.typeo.actual;
-
+ internal_error("typeof implementation unimplemented");
return implements(flags, scope, arg_type, param_type);
}
@@ -814,8 +480,6 @@ int implements(enum match_flags flags, struct scope *scope,
if (!arg_type && !param_type)
return 0;
- /* only the variadic argument in parameters has no type, so any actual
- * type implements it */
/* slight hack: macro arguments also don't have a type, so they will
* also 'implement' type */
if (!param_type)
@@ -824,127 +488,20 @@ int implements(enum match_flags flags, struct scope *scope,
/* at this point, we should always have some type for the argument */
assert(arg_type);
- if (param_type->_type.kind == AST_TYPE_ALIAS ||
- arg_type->_type.kind == AST_TYPE_ALIAS) {
- assert(param_type->_type.next == NULL);
- return implements_alias(flags, scope, arg_type, param_type);
- }
-
-
- if (param_type->_type.kind == AST_TYPE_TYPEOF ||
- arg_type->_type.kind == AST_TYPE_TYPEOF) {
- /* if we're comparing procedure definitions, be more lenient */
- if (!(flags & MATCH_CALL) &&
- param_type->_type.kind != arg_type->_type.kind)
- return 0;
-
+ if (AST_TYPE(param_type).kind == AST_TYPE_TYPEOF)
return implements_typeof(flags, scope, arg_type, param_type);
- }
-
- /* having the arg be a trait is a bit of a special case */
- if (arg_type->_type.kind == AST_TYPE_TRAIT) {
- if (arg_type->_type.trait.actual == NULL)
- return types_match(arg_type, param_type);
-
- return implements(flags, scope, arg_type->_type.trait.actual,
- param_type);
- }
-
- /* TODO: do aliases and traits have to be converted to types? Are
- * there any situations where a trait will have to be followed by
- * some other type? */
- /* if the parameter type is not a trait, it's an actual type and therefore the
- * argument type must be identical to it */
- if (param_type->_type.kind == AST_TYPE_TRAIT) {
- if (param_type->_type.trait.actual == NULL)
- return implements_trait(flags, scope, arg_type,
- param_type);
-
- return implements(flags, scope, arg_type,
- param_type->_type.trait.actual);
- }
-
- if (param_type->_type.kind == AST_TYPE_POINTER) {
- if (arg_type->_type.kind != AST_TYPE_POINTER)
- return 0;
-
- return implements(flags, scope, arg_type->_type.next,
- param_type->_type.next);
- }
-
- if (!types_match(arg_type, param_type))
- return 0;
-
- /* if both types have next elements in them, analyze them as well */
- if (arg_type->_type.next && param_type->_type.next)
- return implements(flags, scope, arg_type->_type.next,
- param_type->_type.next);
-
- /* if this is the last type element in both types, they match */
- if (!arg_type->_type.next && !param_type->_type.next)
- return 1;
-
- /* otherwise, no match */
- return 0;
-}
-
-/* has to be executed in a temporary scope */
-static int match_args(enum match_flags flags, struct scope *scope, int variadic,
- const struct ast_node *args,
- const struct ast_node *params)
-{
- /* no arguments matches to no parameters */
- if (!params && !args)
- return 1;
-
- while (params && args) {
- if (!implements(flags, scope, args->type, params->type))
- return 0;
-
- init_trait_type(params->type, params->type, args->type);
-
- params = params->next;
- args = args->next;
- }
-
- if (args) {
- /* if we have arguments left over and the proc is variadic, we
- * match. The last argument is replaced with the trailing list
- * of arguments beyond the parameter list. */
- if (variadic)
- return 1;
-
- return 0;
- }
- /* we have more parameters compared to arguments, so there's no way we
- * match */
- if (params)
- return 0;
+ if (AST_TYPE(param_type).kind == AST_TYPE_TRAIT)
+ return implements_trait(flags, scope, arg_type, param_type);
- /* we have the same number of arguments and they all implement the
- * parameters, so we match */
- return 1;
+ return types_match(arg_type, param_type);
}
-static int match_params(enum match_flags flags, struct scope *scope,
- int variadic,
+static int match_actual_params(enum match_flags flags, struct scope *scope,
struct ast_node *args, struct ast_node *params)
{
- struct scope *tmp_scope = create_temp_scope(scope);
- /* if the args aren't actualized, we're in the analysis phase? */
- /* TODO: this isn't necessary for actualized procedures */
- struct ast_node *params_clone = clone_ast_node(params);
- if (args->type && actualize_temp_type(tmp_scope, params_clone)) {
- destroy_ast_tree(params_clone);
- destroy_scope(tmp_scope);
- return 0;
- }
-
- int ret = match_args(flags, tmp_scope, variadic, args, params_clone);
- destroy_ast_tree(params_clone);
- destroy_scope(tmp_scope);
- return ret;
+ /** @todo essentially just iterate over the parameters, right? */
+ return 0;
}
static struct ast_node *match_resolve(struct scope *scope,
@@ -984,32 +541,8 @@ static struct ast_node *match_type_construct(struct scope *scope,
return match_resolve(scope, scope->type_construct_resolve, id, args);
}
-int scope_add_macro(struct scope *scope, struct ast_node *macro)
-{
- assert(macro->node_type == AST_MACRO_CONSTRUCT);
- /* TODO: separate between arrays and macros? */
- struct ast_node *id = macro->_macro.id;
- struct ast_node *params = macro->_macro.params;
-
- int macro_exists = (match_macro(scope, id, params) != NULL);
- if (macro_exists) {
- semantic_error(scope->fctx, macro, "macro redefined");
- return -1;
- }
-
- struct visible *new = create_macro(scope, macro);
- if (!new)
- return -1;
-
- int public = scope_flags(scope, SCOPE_PUBLIC);
- if (scope_flags(scope, SCOPE_FILE) && ast_flags(macro, AST_FLAG_PUBLIC))
- return reference_macro(public, scope->parent, new);
-
- return 0;
-}
-
-int add_proc_resolve(struct scope *scope, struct ast_node *proc)
+static int add_proc_resolve(struct scope *scope, struct ast_node *proc)
{
if (!scope->proc_resolve) {
scope->proc_resolve = calloc(1, sizeof(struct resolve));
@@ -1032,7 +565,7 @@ int add_proc_resolve(struct scope *scope, struct ast_node *proc)
return add_resolve(scope, resolve, proc);
}
-int add_macro_resolve(struct scope *scope, struct ast_node *macro)
+static int add_macro_resolve(struct scope *scope, struct ast_node *macro)
{
if (!scope->macro_resolve) {
scope->macro_resolve = calloc(1, sizeof(struct resolve));
@@ -1040,7 +573,7 @@ int add_macro_resolve(struct scope *scope, struct ast_node *macro)
struct resolve *resolve = scope->macro_resolve;
while (resolve) {
- if (identical_ast_nodes(0, resolve->id, macro->_macro.id))
+ if (identical_ast_nodes(0, resolve->id, AST_MACRO_CONSTRUCT(macro).id))
return add_resolve(scope, resolve, macro);
resolve = resolve->next;
@@ -1048,13 +581,34 @@ int add_macro_resolve(struct scope *scope, struct ast_node *macro)
resolve = calloc(1, sizeof(struct resolve));
resolve->root = calloc(1, sizeof(struct resolve_node));
- resolve->id = clone_ast_node(macro->_macro.id);
+ resolve->id = clone_ast_node(AST_MACRO_CONSTRUCT(macro).id);
resolve->next = scope->macro_resolve;
scope->macro_resolve = resolve;
return add_resolve(scope, resolve, macro);
}
+int scope_add_macro(struct scope *scope, struct ast_node *macro)
+{
+ assert(macro->node_type == AST_MACRO_CONSTRUCT);
+ struct ast_node *id = AST_MACRO_CONSTRUCT(macro).id;
+ struct ast_node *params = AST_MACRO_CONSTRUCT(macro).params;
+
+ struct ast_node *exists = match_macro(scope, id, params);;
+ if (exists) {
+ semantic_error(scope->fctx, macro, "macro redefined");
+ semantic_info(scope->fctx, exists, "previously here");
+ return -1;
+ }
+
+ add_macro_resolve(scope, macro);
+
+ if (scope_flags(scope, SCOPE_FILE) && ast_flags(macro, AST_FLAG_PUBLIC))
+ return scope_add_macro(scope->parent, macro);
+
+ return 0;
+}
+
int add_type_construct_resolve(struct scope *scope, struct ast_node *type_construct)
{
if (!scope->type_construct_resolve) {
@@ -1063,7 +617,7 @@ int add_type_construct_resolve(struct scope *scope, struct ast_node *type_constr
struct resolve *resolve = scope->type_construct_resolve;
while (resolve) {
- if (identical_ast_nodes(0, resolve->id, AST_GET(type_construct, id)))
+ if (identical_ast_nodes(0, resolve->id, AST_TYPE_CONSTRUCT(type_construct).id))
return add_resolve(scope, resolve, type_construct);
resolve = resolve->next;
@@ -1071,39 +625,33 @@ int add_type_construct_resolve(struct scope *scope, struct ast_node *type_constr
resolve = calloc(1, sizeof(struct resolve));
resolve->root = calloc(1, sizeof(struct resolve_node));
- resolve->id = clone_ast_node(AST_GET(type_construct, id));
+ resolve->id = clone_ast_node(AST_TYPE_CONSTRUCT(type_construct).id);
resolve->next = scope->type_construct_resolve;
scope->type_construct_resolve = resolve;
return add_resolve(scope, resolve, type_construct);
}
-/* would be useful with scope_remove_proc which also removed all references? */
int scope_add_proc(struct scope *scope, struct ast_node *proc)
{
assert(proc->node_type == AST_PROC);
- struct ast_node *id = proc->_proc.id;
- struct ast_node *sign = proc->_proc.sign;
- struct ast_node *params = sign->_type.sign.params;
+ struct ast_node *id = AST_PROC(proc).id;
+ struct ast_node *sign = AST_PROC(proc).sign;
+ struct ast_node *params = AST_SIGN_TYPE(sign).params;
- struct ast_node *macro_exists = match_proc(scope, id, params);
+ struct ast_node *exists = match_proc(scope, id, params);
- if (macro_exists) {
+ if (exists) {
semantic_error(scope->fctx, proc, "proc redefined");
- semantic_info(scope->fctx, macro_exists, "previously as macro");
+ semantic_info(scope->fctx, exists, "previously here");
return -1;
}
- struct visible *new = create_proc(scope, proc);
- if (!new)
- return -1;
-
add_proc_resolve(scope, proc);
- int public = scope_flags(scope, SCOPE_PUBLIC);
if (scope_flags(scope, SCOPE_FILE) && ast_flags(proc, AST_FLAG_PUBLIC))
- return reference_proc(public, scope->parent, new);
+ return scope_add_proc(scope->parent, proc);
return 0;
}
@@ -1112,86 +660,78 @@ int scope_add_type_construct(struct scope *scope, struct ast_node *type_construc
{
assert(type_construct->node_type == AST_TYPE_CONSTRUCT);
- struct ast_node *id = AST_GET(type_construct, id);
- struct ast_node *params = AST_GET(type_construct, params);
+ struct ast_node *id = AST_TYPE_CONSTRUCT(type_construct).id;
+ struct ast_node *params = AST_TYPE_CONSTRUCT(type_construct).params;
- int type_construct_exists = (match_type_construct(scope, id, params) != NULL);
- if (type_construct_exists) {
+ struct ast_node *exists = match_type_construct(scope, id, params);
+ if (exists) {
semantic_error(scope->fctx, type_construct, "type construct redefined");
+ semantic_info(scope->fctx, exists, "previously here");
return -1;
}
- struct visible *new = create_type_construct(scope, type_construct);
- if (!new)
- return -1;
+ add_type_construct_resolve(scope, type_construct);
- int public = scope_flags(scope, SCOPE_PUBLIC);
if (scope_flags(scope, SCOPE_FILE) && ast_flags(type_construct, AST_FLAG_PUBLIC))
- return reference_type_construct(public, scope->parent, new);
+ return scope_add_type_construct(scope->parent, type_construct);
return 0;
}
-#define FIND_FILE_VISIBLE(name, obj_type) \
- struct ast_node *name(struct scope *scope, struct ast_node *id) \
- { \
- assert(id->node_type == AST_ID); \
- struct ast_node *found = scope_find_##obj_type(scope, id); \
- if (found) { \
- return found; \
- } \
- if (!scope_flags(scope, SCOPE_FILE)) { \
- return file_scope_find_##obj_type(scope->parent, id); \
- } \
- return NULL; \
+static struct ast_node *scope_find_visible(struct visible *v, struct ast_node *id)
+{
+ if (!v)
+ return NULL;
+
+ while (v) {
+ if (identical_ast_nodes(0, v->id, id))
+ return v->node;
+
+ v = v->next;
}
+ return NULL;
+}
+
+struct ast_node *scope_find_type(struct scope *scope, struct ast_node *type)
+{
+ return scope_find_visible(scope->types, type);
+}
+
struct ast_node *file_scope_find_type(struct scope *scope,
struct ast_node *type)
{
assert(type->node_type == AST_ID);
+ if (!scope)
+ return NULL;
+
struct ast_node *found = scope_find_type(scope, type);
if (found)
return found;
- if (!found && !scope_flags(scope, SCOPE_FILE))
+ if (!scope_flags(scope, SCOPE_FILE))
return file_scope_find_type(scope->parent, type);
return NULL;
}
-FIND_FILE_VISIBLE(file_scope_find_var, var);
-FIND_FILE_VISIBLE(file_scope_find_proc, proc);
-FIND_FILE_VISIBLE(file_scope_find_macro, macro);
-
-FIND_FILE_VISIBLE(file_scope_find_alias, alias);
-FIND_FILE_VISIBLE(file_scope_find_trait, trait);
-
-struct ast_node *file_scope_find(struct scope *scope, struct ast_node *id)
+struct ast_node *scope_find_var(struct scope *scope, struct ast_node *var)
{
- /* TODO: should probably check for incoming search and filter out params
- * etc */
- assert(id->node_type == AST_ID);
-
- struct ast_node *found = file_scope_find_var(scope, id);
- if (found)
- return found;
-
- found = file_scope_find_proc(scope, id);
- if (found)
- return found;
+ return scope_find_visible(scope->vars, var);
+}
- found = file_scope_find_macro(scope, id);
- if (found)
- return found;
+struct ast_node *file_scope_find_var(struct scope *scope, struct ast_node *var)
+{
+ assert(var->node_type == AST_ID);
+ if (!scope)
+ return NULL;
- found = file_scope_find_alias(scope, id);
+ struct ast_node *found = scope_find_var(scope, var);
if (found)
return found;
- found = file_scope_find_trait(scope, id);
- if (found)
- return found;
+ if (!scope_flags(scope, SCOPE_FILE))
+ return file_scope_find_var(scope->parent, var);
return NULL;
}
@@ -1204,43 +744,11 @@ struct ast_node *scope_resolve_macro(struct scope *scope, struct ast_node *macro
return match_macro(scope, id, args);
}
-static int trait_contains_proc(enum match_flags flags, struct scope *scope,
- struct ast_node *trait,
- struct ast_node *id, struct ast_node *args)
-{
- assert(trait->_type.kind == AST_TYPE_TRAIT);
- trait = trait->_type.trait.trait;
-
- struct ast_node *elem = trait->_trait.body;
- if (elem)
- do {
- if (elem->node_type != AST_PROC)
- continue;
-
- if (!identical_ast_nodes(0, elem->_proc.id, id))
- continue;
-
- /* TODO: should I check for return type here as well? */
- int variadic = ast_flags(elem, AST_FLAG_VARIADIC);
- struct ast_node *sign = elem->_proc.sign;
- struct ast_node *params = sign->_type.sign.params;
- if (match_params(flags, scope, variadic, args, params))
- return 1;
-
- } while ((elem = elem->next));
-
- return 0;
-}
-
struct ast_node *scope_resolve_proc(struct scope *scope, struct ast_node *call)
{
- /* TODO: we should prefer specialized procs over generic ones.
- * i.e. do_stuff(a u32){} should be preferred over do_stuff(a some_type){},
- * when u32 implements some_type. */
assert(call->node_type == AST_CALL);
struct ast_node *id = call->_call.id;
struct ast_node *args = call->_call.args;
-
return match_proc(scope, id, args);
}
@@ -1263,10 +771,10 @@ struct ast_node *scope_resolve_actual(struct scope *scope,
assert(!ast_flags(actual, AST_FLAG_VARIADIC));
/* could also check that arguments aren't traits */
- struct ast_node *args = call->_call.args;
- struct ast_node *sign = actual->_proc.sign;
- struct ast_node *params = sign->_type.sign.params;
- if (match_params(0, scope, 0, args, params))
+ struct ast_node *args = AST_CALL(call).args;
+ struct ast_node *sign = AST_PROC(actual).sign;
+ struct ast_node *params = AST_SIGN_TYPE(sign).params;
+ if (match_actual_params(0, scope, args, params))
return actual;
} while ((prev = cur));
@@ -1302,53 +810,6 @@ struct ast_node *file_scope_resolve_call(struct scope *scope,
return NULL;
}
-struct ast_node *scope_resolve_type(struct scope *scope, struct ast_node *type)
-{
- struct ast_node *id = NULL;
- switch (type->node_type) {
- case AST_ID: id = type; break;
- case AST_TYPE:
- assert(type->_type.kind == AST_TYPE_ID);
- id = type->_type.id;
- break;
-
- case AST_ALIAS:
- id = type->_alias.id;
- break;
-
- case AST_TRAIT:
- id = type->_trait.id;
- break;
-
- case AST_STRUCT:
- id = type->_struct.id;
- break;
-
- case AST_ENUM:
- id = type->_enum.id;
- break;
-
- default:
- semantic_error(scope->fctx, type, "unknown type");
- return NULL;
- }
-
- return scope_find_type(scope, id);
-}
-
-struct ast_node *file_scope_resolve_type(struct scope *scope,
- struct ast_node *type)
-{
- struct ast_node *found = scope_resolve_type(scope, type);
- if (found)
- return found;
-
- if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_resolve_type(scope->parent, type);
-
- return NULL;
-}
-
struct ast_node *file_scope_resolve_macro(struct scope *scope, struct ast_node *macro)
{
struct ast_node *found = scope_resolve_macro(scope, macro);
@@ -1356,17 +817,13 @@ struct ast_node *file_scope_resolve_macro(struct scope *scope, struct ast_node *
return found;
if (!scope_flags(scope, SCOPE_FILE))
- return file_scope_resolve_type(scope->parent, macro);
+ return file_scope_resolve_macro(scope->parent, macro);
return NULL;
}
/* this might be useful somewhere else as well */
-static const char *default_types[] = {"u8", "u16", "u32", "u64",
- "i8" "i16", "i32", "i64",
- "usize", "isize",
- "f32", "f64",
- "bool", "void"};
+static const char *default_types[] = {"void", "i9", "i27"};
/* TODO: add error checking */
int scope_add_defaults(struct scope *root)
@@ -1379,35 +836,16 @@ int scope_add_defaults(struct scope *root)
if (!n)
return -1;
- struct ast_node *a = gen_type(AST_TYPE_ID, n, NULL, NULL);
+ struct ast_node *a = gen_type(AST_TYPE_PRIMITIVE, n, NULL, NULL);
if (!a)
return -1;
- scope_add_type(root, a);
+ scope_add_type(root, n, a);
}
return 0;
}
-void scope_destroy_defaults(struct scope *scope)
-{
- /* just enough data to get through to the actual default aliases */
- struct ast_node type = {0};
- type.node_type = AST_ID;
-
- for (size_t i = 0;
- i < sizeof(default_types) / sizeof(default_types[0]);
- ++i) {
- type._id.id = default_types[i];
- struct ast_node *n = scope_find_alias(scope, &type);
- /* something is afoot, but at least try to free the rest */
- if (!n)
- continue;
-
- destroy_ast_node(n);
- }
-}
-
void scope_add_scope(struct scope *parent, struct scope *child)
{
assert(parent);
@@ -1462,19 +900,6 @@ struct ast_node *scope_find_actual(struct scope *scope, struct ast_node *node)
return find_actual(scope->actuals, node);
}
-int scope_add_scratch(struct scope *scope, struct ast_node *scratch)
-{
- struct scratch *new = create_scratch(scratch);
- if (!new) {
- internal_error("failed allocating scratch node");
- return -1;
- }
-
- new->next = scope->scratch;
- scope->scratch = new;
- return 0;
-}
-
struct scope *create_temp_scope(struct scope *parent)
{
struct scope *scope = create_scope();