From 5b5f6321c743e9a521e45865312a76ae0bffe450 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 12 Nov 2023 19:19:51 +0200 Subject: start implementing new generics handling + Still requires a lot of fixes here and there --- include/ek/ast.h | 99 +++++++++++++++++++++++++++++------------------------- include/ek/debug.h | 1 + include/ek/scope.h | 67 ++++++++++++------------------------ 3 files changed, 77 insertions(+), 90 deletions(-) (limited to 'include') diff --git a/include/ek/ast.h b/include/ek/ast.h index feece73..421d247 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -10,6 +10,8 @@ * Abstract syntax tree handling. */ +#define AST_GET(x, y) x->x.y + /** Binary operands, that is they take two arguments and produce a result. */ enum ast_binops { /** Add, \c + */ @@ -22,16 +24,8 @@ enum ast_binops { AST_DIV, /** Remainder, \c % */ AST_REM, - /** Bitwise exclusive or, \c ^ */ - AST_XOR, - /** Raise to power \c ^^ (likely not necessary) */ - AST_POW, - /** Bitwise and, \c & */ - AST_AND, /** Logical and, \c && */ AST_LAND, - /** Bitwise or, \c | */ - AST_OR, /** Logical or, \c ||*/ AST_LOR, /** Left shift (logical), \c << @todo add arithmetic shifts? */ @@ -48,12 +42,6 @@ enum ast_binops { AST_ASSIGN_DIV, /** Assigning remainder, \c %= */ AST_ASSIGN_REM, - /** Assigning bitwise and, \c &= */ - AST_ASSIGN_AND, - /** Assigning bitwise or, \c |= */ - AST_ASSIGN_OR, - /** Assigning bitwise exclusive or, \c ^= */ - AST_ASSIGN_XOR, /** Assigning logical left shift, \c >>= */ AST_ASSIGN_LSHIFT, /** Assigning logical right shift, \c <<= */ @@ -82,10 +70,10 @@ enum ast_unops { AST_REF, /** Dereferencing, \c ' */ AST_DEREF, - /** Bitwise negation, i.e. inverting bits, \c ~ */ - AST_NOT }; +#define NULL_LOC() ((struct src_loc){0, 0, 0, 0}) + /** Represents a source location, spanning over some bit of code. */ struct src_loc { /** First line of interesting text. */ @@ -110,8 +98,9 @@ enum ast_node_type { AST_INIT, /** Assignment. */ AST_ASSIGN, - /** Call. We don't know to what yet: macro, array or procedure.*/ + /** Call procedure. */ AST_CALL, + AST_ARR_ACCESS, /** Sizeof. */ AST_SIZEOF, /** Cast. */ @@ -119,10 +108,10 @@ enum ast_node_type { /** Defer. */ AST_DEFER, /** Macro definition. */ - AST_MACRO, - AST_MACRO_EXPANSION, - /** Reference to previous expression, i.e. \c @ */ - AST_LAST, + AST_MACRO_CONSTRUCT, + AST_MACRO_EXPAND, + AST_TYPE_CONSTRUCT, + AST_TYPE_EXPAND, /** Procedure definition. */ AST_PROC, /** Goto. */ @@ -162,8 +151,6 @@ enum ast_node_type { AST_IMPORT, /** Enum definition. */ AST_ENUM, - /** Union definition. */ - AST_UNION, /** Enum constant value. */ AST_VAL, /** Switch. */ @@ -310,6 +297,11 @@ struct ast_label { struct ast_node *defers; }; +struct ast_arr_access { + struct ast_node *base; + struct ast_node *idx; +}; + /** Goto node. */ struct ast_goto { /** Name of label to jump to. */ @@ -394,7 +386,7 @@ struct ast_defer { }; /** Macro definition. */ -struct ast_macro { +struct ast_macro_construct { /** Name of macro. */ struct ast_node *id; /** Parameters macro takes. */ @@ -403,7 +395,18 @@ struct ast_macro { struct ast_node *body; }; -struct ast_macro_expansion { +struct ast_macro_expand { + struct ast_node *id; + 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; }; @@ -648,16 +651,6 @@ struct ast_struct { struct ast_node *body; }; -/** Union definition. */ -struct ast_union { - /** Name of union. */ - struct ast_node *id; - /** List of type parameters, if any. */ - struct ast_node *generics; - /** Body. */ - struct ast_node *body; -}; - /** Enum member constant value. */ struct ast_val { /** Name of member. */ @@ -741,8 +734,9 @@ struct ast_node { /** Data relevant to kind. */ union { + struct ast_arr_access arr_access; /** Binary operation. */ - struct ast_binop _binop; + struct ast_binop binop; /** Unary operation. */ struct ast_unop _unop; /** Call. */ @@ -750,8 +744,10 @@ struct ast_node { /** Cast. */ struct ast_cast _cast; /** Macro definition. */ - struct ast_macro _macro; - struct ast_macro_expansion _macro_expansion; + struct ast_macro_construct _macro; + struct ast_macro_expand _macro_expand; + struct ast_type_construct type_construct; + struct ast_type_expand type_expand; /** Procedure definition. */ struct ast_proc _proc; /** Goto. */ @@ -794,8 +790,6 @@ struct ast_node { struct ast_enum _enum; /** Structure definition. */ struct ast_struct _struct; - /** Union definition. */ - struct ast_union _union; /** Enum value. */ struct ast_val _val; /** Switch case. */ @@ -819,6 +813,8 @@ struct ast_node { }; }; +struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, struct src_loc loc); + /** * Generate binary operation node. * @@ -828,7 +824,9 @@ struct ast_node { * @return Corresponding AST node. */ struct ast_node *gen_binop(enum ast_binops op, - struct ast_node *left, struct ast_node *right); + struct ast_node *left, + struct ast_node *right, + struct src_loc loc); /** * Generate unary operation. @@ -854,7 +852,7 @@ struct ast_node *gen_call(struct ast_node *id, struct ast_node *args); * @param id ID. * @return Corresponding AST node. */ -struct ast_node *gen_id(const char *id); +struct ast_node *gen_id(const char *id, struct src_loc loc); /** * Generate constant integer. @@ -947,9 +945,22 @@ 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(struct ast_node *id, struct ast_node *params, +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 ast_node *gen_type_construct(struct ast_node *id, + struct ast_node *params, + struct ast_node *body, + 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); + /** * Generate if. * @@ -1079,8 +1090,6 @@ struct ast_node *gen_alias(struct ast_node *id, struct ast_node *type); */ struct ast_node *gen_trait(struct ast_node *id, struct ast_node *body); -struct ast_node *gen_macro_expansion(struct ast_node *id, struct ast_node *args); - /** * Generate import; * diff --git a/include/ek/debug.h b/include/ek/debug.h index d222cf4..588fc6b 100644 --- a/include/ek/debug.h +++ b/include/ek/debug.h @@ -121,6 +121,7 @@ void semantic_error(struct file_ctx ctx, struct ast_node *node, const char *fmt, * @param fmt Format string. Follows standard printf() formatting. */ void internal_error(const char *fmt, ...); +void internal_warn(const char *fmt, ...); /** Issue categorization. */ enum issue_level { diff --git a/include/ek/scope.h b/include/ek/scope.h index 422af0f..020aaaa 100644 --- a/include/ek/scope.h +++ b/include/ek/scope.h @@ -75,13 +75,13 @@ struct actual { * matched against this resolution tree to know * which callable to choose. */ -struct callable { - /** Resolve tree of callable. */ - struct proc_node *root; - /** AST node ID of callable. */ +struct resolve { + /** Resolve tree of resolve. */ + struct resolve_node *root; + /** AST node ID of resolve. */ struct ast_node *id; - /** Next callable node. */ - struct callable *next; + /** Next resolve node. */ + struct resolve *next; }; /** A parameter node in the procedure resolution tree. */ @@ -89,7 +89,7 @@ struct param_node { /** Parameter type. */ struct ast_node *type; /** Fully resolved procedure if there is no next node. */ - struct proc_node *proc; + struct resolve_node *resolved; /** Next parameter node in current parameter slot. */ struct param_node *next; }; @@ -134,27 +134,12 @@ struct param_node { * do_stuff(some_struct(u8)){} // ERR * @endverbatim */ -struct proc_node { - /** List of primitive types of the current parameter slot. */ - struct param_node *primitives; - /** - * Referential type for parameter slot. - * Each parameter slot only allows a single referential type, because - * it would be too difficult to check if a reference is identical - * to another. Some special cases are somewhat trivially checked, but - * I haven't been able to come up with a generic enough check. - */ - struct param_node *referential; - - /** - * Fallback generic type for parameter slot. - * Each parameter slot only allows a single generic type, because - * it would be too difficult to check if two types have overlap. - */ - struct param_node *fallback; +struct resolve_node { + /** List of parameters of the current parameter slot. */ + struct param_node *params; /** Next procedure with parameter slot. */ - struct ast_node *proc; + struct ast_node *resolved; }; @@ -197,8 +182,6 @@ struct scope { /** { types */ /** Enums visible in scope. */ struct visible *enums; - /** Unions visible in scope. */ - struct visible *unions; /** Structs visible in scope. */ struct visible *structs; @@ -213,14 +196,15 @@ struct scope { struct visible *builtins; /** - * Templates visible in scope. + * 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; /** } */ - /** { Callables, incl. variables. */ + struct visible *type_constructs; + /** * Variables visible in scope. * @note Only some variables are callable, namely array variables. @@ -231,19 +215,10 @@ struct scope { struct visible *macros; /** Procedures visible in scope. */ struct visible *procs; - /** } */ - /** { callables */ - /** - * Anything callable. - * @note currently each type of callable is first - * collected into its corresponding visible list, - * \p vars, \p macros or \p procs, but after the initial - * program analysis they are merged together to create a callable - * resolve tree. - */ - struct callable *callable; - /** } */ + struct resolve *proc_resolve; + struct resolve *macro_resolve; + struct resolve *type_construct_resolve; }; /** Flags for matching objects during search. */ @@ -428,7 +403,9 @@ int scope_add_alias(struct scope *scope, struct ast_node *alias); * @param type_template Template to add to scope. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_template(struct scope *scope, struct ast_node *type_template); +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. @@ -546,7 +523,7 @@ struct ast_node *scope_find_alias(struct scope *scope, struct ast_node *id); * @return Pointer to the AST node corresponding to \p id if found, * otherwise \c NULL. */ -struct ast_node *scope_find_template(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. @@ -617,7 +594,7 @@ struct ast_node *file_scope_find_alias(struct scope *scope, * @return Pointer to the AST node corresponding to \p id if found, * otherwise \c NULL. */ -struct ast_node *file_scope_find_template(struct scope *scope, +struct ast_node *file_scope_find_trait(struct scope *scope, struct ast_node *id); /** -- cgit v1.3