diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/ek/ast.h | 76 | ||||
| -rw-r--r-- | include/ek/ops.h | 10 | ||||
| -rw-r--r-- | include/ek/scope.h | 284 |
3 files changed, 44 insertions, 326 deletions
diff --git a/include/ek/ast.h b/include/ek/ast.h index e078f59..201b746 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -32,18 +32,17 @@ #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_CONSTRUCT_TYPE(x) x->_type._construct #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_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_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 */ @@ -148,7 +147,6 @@ enum ast_node_type { /** Macro definition. */ AST_MACRO_CONSTRUCT, AST_MACRO_EXPAND, - AST_TYPE_CONSTRUCT, AST_TYPE_EXPAND, /** Procedure definition. */ AST_PROC, @@ -228,8 +226,7 @@ enum ast_type_kind { AST_TYPE_PRIMITIVE, /** Array. */ AST_TYPE_ARR, - /** Typeof expression. */ - AST_TYPE_TYPEOF, + AST_TYPE_CONSTRUCT, /** Trait. */ AST_TYPE_TRAIT, /** Pointer to a type. */ @@ -366,6 +363,8 @@ struct trait_implemented { struct ast_trait { /** Name of trait. */ struct ast_node *id; + /** Parameters to construct concrete type from trait. */ + struct ast_node *params; /** Body of trait. */ struct ast_node *body; /** List of types that implement this trait. */ @@ -401,7 +400,7 @@ struct ast_unop { /** A call. */ struct ast_call { /** Name to call, whatever it may be. */ - struct ast_node *id; + struct ast_node *expr; /** List of arguments to call. */ struct ast_node *args; }; @@ -427,12 +426,6 @@ struct ast_macro_expand { struct ast_node *args; }; -struct ast_type_construct { - struct ast_node *id; - struct ast_node *params; - struct ast_node *body; -}; - struct ast_type_expand { struct ast_node *id; struct ast_node *args; @@ -550,7 +543,7 @@ struct ast_type { /** Type kind. */ enum ast_type_kind kind; /** - * Next type element in whole type. I.e. 'u32 is two elements, one + * Next type element in whole type. I.e. *i9 is two elements, one * AST_TYPE_POINTER and one AST_TYPE_ID. */ struct ast_node *next; @@ -565,6 +558,11 @@ struct ast_type { } _id; struct { + struct ast_node *id; + struct ast_node *args; + } _construct; + + struct { enum ast_primitive type; } _primitive; @@ -578,12 +576,6 @@ struct ast_type { struct ast_node *base; } _ptr; - /** Typeof. */ - struct { - /** Expression to take type of. */ - struct ast_node *expr; - } _typeof; - /** Procedure. */ struct { /** Name. */ @@ -764,7 +756,6 @@ struct ast_node { /** Macro definition. */ struct ast_macro_construct _macro_construct; struct ast_macro_expand _macro_expand; - struct ast_type_construct _type_construct; struct ast_type_expand _type_expand; /** Procedure definition. */ struct ast_proc _proc; @@ -831,7 +822,8 @@ struct ast_node { }; }; -struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, struct src_loc loc); +struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, + struct src_loc loc); /** * Generate binary operation node. @@ -843,8 +835,8 @@ struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, str */ struct ast_node *gen_binop(enum ast_binops op, struct ast_node *left, - struct ast_node *right, - struct src_loc loc); + struct ast_node *right, + struct src_loc loc); /** * Generate unary operation. @@ -862,7 +854,8 @@ struct ast_node *gen_unop(enum ast_unops op, struct ast_node *expr); * @param args Arguments to call. * @return Corresponding AST node. */ -struct ast_node *gen_call(struct ast_node *id, struct ast_node *args); +struct ast_node *gen_call(struct ast_node *id, struct ast_node *args, + struct src_loc loc); /** * Generate ID. @@ -963,21 +956,18 @@ struct ast_node *gen_ctrl(enum ast_ctrl_kind kind, struct src_loc loc); * @param body Macro body. * @return Corresponding AST node. */ -struct ast_node *gen_macro_construct(struct ast_node *id, struct ast_node *params, - struct ast_node *body); - -struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args, struct src_loc loc); +struct ast_node *gen_macro_construct(struct ast_node *id, + struct ast_node *params, + struct ast_node *body); -struct ast_node *gen_type_construct(struct ast_node *id, - struct ast_node *params, - struct ast_node *body, - struct src_loc loc); +struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args, + struct src_loc loc); /** @todo change args to type type when I figure out how it should be * constructed */ struct ast_node *gen_type_expand(struct ast_node *id, - struct ast_node *args, - struct src_loc loc); + struct ast_node *args, + struct src_loc loc); /** * Generate if. @@ -1018,8 +1008,9 @@ struct ast_node *gen_primitive(enum ast_primitive type, struct src_loc loc); * @param rets Return type, when applicable. * @return Corresponding AST node. */ -struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *id, - struct ast_node *decl, struct ast_node *rets); +struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *t2, + struct ast_node *t1, + struct src_loc loc); /** * Generate block. @@ -1038,7 +1029,7 @@ struct ast_node *gen_block(struct ast_node *body); * @return Corresponding AST node. */ struct ast_node *gen_var(struct ast_node *id, struct ast_node *type, - struct ast_node *init); + struct ast_node *init, struct src_loc loc); /** * Generate lambda. @@ -1069,7 +1060,7 @@ struct ast_node *gen_proc(struct ast_node *id, struct ast_node *type, * @param id Name to do dot with. * @return Corresponding AST node. */ -struct ast_node *gen_dot(struct ast_node *expr, struct ast_node *id); +struct ast_node *gen_dot(struct ast_node *expr, struct ast_node *id, struct src_loc loc); /** * Generate enum definition. @@ -1107,7 +1098,8 @@ struct ast_node *gen_alias(struct ast_node *id, struct ast_node *type); * @param body Body. * @return Corresponding AST node. */ -struct ast_node *gen_trait(struct ast_node *id, struct ast_node *body); +struct ast_node *gen_trait(struct ast_node *id, struct ast_node *params, + struct ast_node *body, struct src_loc loc); /** * Generate import; diff --git a/include/ek/ops.h b/include/ek/ops.h index 0d9d433..a7672d7 100644 --- a/include/ek/ops.h +++ b/include/ek/ops.h @@ -2,6 +2,7 @@ #define EK_OPS_H #include <ek/ast.h> +#include <stdio.h> enum loc_kind { LOC_NONE, LOC_REG, LOC_MEM @@ -10,8 +11,6 @@ enum loc_kind { struct loc { enum loc_kind kind; struct loc *next; - size_t start; - size_t end; size_t reg; long long off; size_t width; @@ -50,10 +49,7 @@ struct ops { struct op *head; }; -struct ops *create_ops(); -void destroy_ops(struct ops *ops); -int lower_ops(struct scope *root, struct ops *ops); -int alloc_regs(struct ops *ops); -int print_asm(struct ops *ops, const char *output); +int lower_ops(struct scope *root, const char *fname); +int print_asm(struct ops *ops, FILE *f); #endif /* EK_OPS_H */ diff --git a/include/ek/scope.h b/include/ek/scope.h index 10b0aad..9c4224e 100644 --- a/include/ek/scope.h +++ b/include/ek/scope.h @@ -49,83 +49,6 @@ struct actual { struct actual *next; }; -/** - * Callable nodes visible to scope. - * - * Each callable consists of an ID and - * a resolution tree built from parameters the - * callable can take. - * Parameters passed to the callable are - * matched against this resolution tree to know - * which callable to choose. - */ -struct resolve { - /** Resolve tree of resolve. */ - struct resolve_node *root; - /** AST node ID of resolve. */ - struct ast_node *id; - /** Next resolve node. */ - struct resolve *next; -}; - -/** A parameter node in the procedure resolution tree. */ -struct param_node { - /** Parameter type. */ - struct ast_node *type; - /** Fully resolved procedure if there is no next node. */ - struct resolve_node *resolved; - /** Next parameter node in current parameter slot. */ - struct param_node *next; -}; - -/** - * A procedure node in the resolution tree. - * - * A resolution tree is how Ek chooses which overloaded callable - * to choose from. For example, - * - * @verbatim - * do_stuff(u8, f32){} - * do_stuff(u8, f64){} - * do_stuff(u16, f32){} - * @endverbatim - * - * generates a resolution tree of the form - * @verbatim - * callable: - * do_stuff -> u8 -> f32 - * -> f64 - * u16 -> f32 - * @endverbatim - * - * When a callable is called with some arguments, the argument's types - * are actualized and using the resolve tree, the correct do_stuff is chosen. - * - * Additionally, interfaces are allowed, but only as a 'fallback'. That is, if - * no trivial parameter type matches the argument type, the fallback is checked, - * and if the argument type doesn't implement the fallback, the resolution - * is considered to have failed. - * - * Self-refential parameter types are similarly checked after primitive types. - * - * @note Generic structures without type arguments are considered primitive, - * as are fully qualified generic structures, anything between is disallowed. - * Eg. - * @verbatim - * struct some_struct (a A, b B) {...} - * do_stuff(some_struct){...} // OK - * do_stuff(some_struct(u8, u16)){} // OK - * do_stuff(some_struct(u8)){} // ERR - * @endverbatim - */ -struct resolve_node { - /** List of parameters of the current parameter slot. */ - struct param_node *params; - - /** Next procedure with parameter slot. */ - struct ast_node *resolved; -}; - struct types { struct ast_node *id; struct ast_node *type; @@ -165,35 +88,12 @@ struct scope { */ struct actual *actuals; - /** { types */ - + struct visible *vars; + struct visible *procs; + struct visible *macros; struct visible *types; - /** } */ - struct visible *type_constructs; - - /** - * Variables visible in scope. - * @note Only some variables are callable, namely array variables. - * @todo Could maybe add separate array list instead of a variable list? - */ - struct visible *vars; - - struct resolve *proc_resolve; - struct resolve *macro_resolve; - struct resolve *type_construct_resolve; -}; - -/** Flags for matching objects during search. */ -enum match_flags { - /** Search globally, not just in current scope. */ - MATCH_GLOBAL = (1 << 0), - /** - * Match call arguments to parameters. - * If this flag is not present, only the name is matched. - */ - MATCH_CALL = (1 << 1), }; /** @@ -236,17 +136,6 @@ void destroy_visible(struct scope *scope, struct visible *visible); void destroy_scope(struct scope *scope); /** - * Create temporary scope. - * Adds \p parent as the parent of the scope, but doesn't add the new scope - * to the list of children \p parent has. - * Caller is responsible for destroying the temporary scope. - * - * @param parent The temporary scope's parent. - * @return New temporary scope. - */ -struct scope *create_temp_scope(struct scope *parent); - -/** * Add default stuff to scope, mainly builtin types. * * @param root Scope to add default stuff to. @@ -327,7 +216,8 @@ 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 *id, struct ast_node *type); +int scope_add_type(struct scope *scope, struct ast_node *id, + struct ast_node *type); /** * Add procedure to scope. @@ -359,53 +249,7 @@ int scope_add_macro(struct scope *scope, struct ast_node *macro); */ int scope_add_trait(struct scope *scope, struct ast_node *trait); -int scope_add_type_construct(struct scope *scope, struct ast_node *type_construct); - -/** - * Add an already allocated visible variable node to scope. - * After initial analysis, preallocated variable nodes are actualized - * and added back into the scope to build up the resolution tree. - * - * @param scope Scope to add variable node to. - * @param var Variable to to add to scope. - * @return \c 0 when succesful, non-zero otherwise. - */ -int scope_add_existing_var(struct scope *scope, struct visible *var); - -/** - * Add an already allocated visible procedure node to scope. - * After initial analysis, preallocated procedure nodes are (partially) - * actualized and added back into the scope to build up the resolution tree. - * - * @param scope SCope to add procedure node to. - * @param proc Procedure to add to scope. - * @return \c 0 when succesful, non-zero otherwise. - */ -int scope_add_existing_proc(struct scope *scope, struct visible *proc); - -/** - * Find an actualized AST node with ID in \p scope. - * Since actuals are file global, technically no need for a file_* - * @note Doesn't do any resolution. See scope_resolve_actual(). - * - * @param scope Scope to look in. - * @param id ID of actual to find. - * @return Pointer to the actualized AST node corresponding to \p id if found, - * otherwise \c NULL. - */ -struct ast_node *scope_find_actual(struct scope *scope, struct ast_node *id); - -/** - * Find anything with ID in \p scope. - * @note Only looks in the current scope, so doesn't see anything outside - * of it. See file_scope_find(). - * - * @param scope Scope to look in. - * @param id ID of whatever to find. - * @return Pointer to the AST node corresponding to \p id if found, - * otherwise \c NULL. - */ -struct ast_node *scope_find(struct scope *scope, struct ast_node *id); +int scope_resolve(struct scope *scope); /** * Find a variable with ID in \p scope. @@ -480,16 +324,6 @@ struct ast_node *scope_find_alias(struct scope *scope, struct ast_node *id); struct ast_node *scope_find_trait(struct scope *scope, struct ast_node *id); /** - * Find anything with ID visible to \p scope. - * - * @param scope Scope to look in. - * @param id ID of whatever to find. - * @return Pointer to the AST node corresponding to \p id if found, - * otherwise \c NULL. - */ -struct ast_node *file_scope_find(struct scope *scope, struct ast_node *id); - -/** * Find a variable with ID visible to \p scope. * * @param scope Scope to look in. @@ -549,110 +383,6 @@ struct ast_node *file_scope_find_alias(struct scope *scope, * otherwise \c NULL. */ struct ast_node *file_scope_find_trait(struct scope *scope, - struct ast_node *id); - -/** - * Try to resolve a call to an array in \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to an array. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *scope_resolve_arr(struct scope *scope, struct ast_node *call); - -/** - * Try to resolve a call to a macro in \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to a macro. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *scope_resolve_macro(struct scope *scope, - struct ast_node *call); - -/** - * Try to resolve a call to an actualized node in \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to an actualized node. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *scope_resolve_actual(struct scope *scope, - struct ast_node *call); - -/** - * Try to resolve a call to a procedure in \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to a procedure. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *scope_resolve_proc(struct scope *scope, struct ast_node *call); - -/** - * Try to resolve a call to an AST node in \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to an AST node. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *scope_resolve_call(struct scope *scope, struct ast_node *call); - -/** - * Try to resolve a call to an AST node visible to \p scope. - * - * @param scope Scope to look in. - * @param call AST call node to try and match to an AST node. - * @return Pointer to the AST node corresponding to \p call if found, - * otherwise \c NULL. - */ -struct ast_node *file_scope_resolve_call(struct scope *scope, - struct ast_node *call); - -struct ast_node *file_scope_resolve_macro(struct scope *scope, - struct ast_node *macro); - -/** - * Check if \p arg_type implements \p param_type. - * - * A type implement another type if - * a) They resolve to the same primitive type after alias and expression substitutions - * b) One type is a trait and the other type has all members and - * procedures specified in the trait. - * - * \p arg_type should never be a trait, so I suppose it's undefined if a trait - * implements another trait. - * - * @param flags Flags for resolution. - * @param scope Scope to check types in. - * @param arg_type Argument type. - * @param param_type Parameter type. - * @return \c 1 if \p arg_type implements \p param_type, \c 0 otherwise. - */ -int implements(enum match_flags flags, struct scope *scope, - struct ast_node *arg_type, - struct ast_node *param_type); - -/** - * Check if type is primitive. - * - * @param type Type to check. - * @return \c 1 if \p type is primitive, \c 0 otherwise. - */ -int primitive_type(struct ast_node *type); - -/** - * Check if type is fully qualified. - * A fully qualified type is a struct or union with all type parameters filled. - * - * @param type Type to check. - * @return \c 1 if \p type is fully qualified, \c 0 otherwise. - */ -int fully_qualified(struct ast_node *type); + struct ast_node *id); #endif /* SCOPE_H */ |
