diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/ek/actualize.h | 61 | ||||
| -rw-r--r-- | include/ek/ast.h | 1546 | ||||
| -rw-r--r-- | include/ek/debug.h | 20 | ||||
| -rw-r--r-- | include/ek/lower.h | 2 | ||||
| -rw-r--r-- | include/ek/parser.h | 2 | ||||
| -rw-r--r-- | include/ek/scope.h | 61 | ||||
| -rw-r--r-- | include/ek/vec.h | 3 |
7 files changed, 495 insertions, 1200 deletions
diff --git a/include/ek/actualize.h b/include/ek/actualize.h index 486f19e..9dc5948 100644 --- a/include/ek/actualize.h +++ b/include/ek/actualize.h @@ -25,47 +25,7 @@ * @param b Type to compare against \p a. * @return \c 1 if types match, \c 0 otherwise. */ -int types_match(struct ast_node *a, struct ast_node *b); - -/** - * Replace type in \p type that matches with \p from - * with \p to. - * - * @param type Whole type to replace part in. - * @param from Part of type to replace. - * @param to Type to replace \p from with. - */ -void replace_type(struct ast_node *type, - struct ast_node *from, struct ast_node *to); - -/** - * Loop over parameters and replace types that match with \p param_type - * with \p arg_type. - * - * @param param Parameters to replace types for. - * @param param_type Type to replace with \p arg_type. - * @param arg_type Type to replace \p param_type with. - */ -void replace_param_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. - * - * @param type Type to extract trait from. - * @return Pointer to trait node when found, \c NULL otherwise. - */ -struct ast_node *extract_trait(struct ast_node *type); - -/** - * Extract typeof expression. - * - * @param type Type to extract typeof from. - * @return Pointer to typeof expression node when found, \c NULL otherwise. - */ -struct ast_node *extract_typeof(struct ast_node *type); +int types_match(struct type *a, struct type *b); /** * Analyze raw AST, assumed to be file scope. @@ -77,23 +37,6 @@ struct ast_node *extract_typeof(struct ast_node *type); * @param tree Raw AST to analyze. * @return \c 0 when successful, non-zero otherwise. */ -int analyze_root(struct scope *scope, struct ast_node *tree); - -/** - * Start actual compilation by trying to actualize main. - * - * @param scope Scope \c main() should be visible to, likely root scope. - * @return \c 0 when succesful, non-zero otherwise. - */ -int actualize_main(struct scope *scope); - -/** - * Create temporary actualization context and actualizes \p type within it. - * - * @param scope Scope to actualize \p type in. - * @param type Type to actualize. - * @return \c 0 when succesful, non-zero otherwise. - */ -int actualize_temp_type(struct scope *scope, struct ast_node *type); +int analyze_root(struct scope *scope, struct ast *tree); #endif /* ANALYZE_H */ diff --git a/include/ek/ast.h b/include/ek/ast.h index f7c6201..27e82e3 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -5,6 +5,7 @@ #define AST_H #include <stddef.h> +#include <stdbool.h> /** * @file ast.h @@ -12,118 +13,6 @@ * Abstract syntax tree handling. */ -#define AST_ID(x) x->_id -#define AST_AS(x) x->_as -#define AST_DOT(x) x->_dot -#define AST_UNOP(x) x->_unop -#define AST_IMPORT(x) x->_import -#define AST_ALIAS(x) x->_alias -#define AST_TRAIT(x) x->_trait -#define AST_CAST(x) x->_cast -#define AST_PROC(x) x->_proc -#define AST_VAR(x) x->_var -#define AST_RETURN(x) x->_return -#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_ASSIGN(x) x->_assign -#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_EXPAND(x) x->_type_expand -#define AST_IF(x) x->_if -#define AST_CASE(x) x->_case -#define AST_SWITCH(x) x->_switch -#define AST_VAL(x) x->_val -#define AST_EMBED(x) x->_embed -#define AST_CTRL(x) x->_ctrl -#define AST_WHILE(x) x->_while -#define AST_FOR(x) x->_for -#define AST_DEFER(x) x->_defer -#define AST_BINOP(x) x->_binop -#define AST_LABEL(x) x->_label -#define AST_GOTO(x) x->_goto -#define AST_INIT(x) x->_init -#define AST_SIZEOF(x) x->_sizeof -#define AST_FETCH(x) x->_fetch - -#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_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 { - /** Add, \c + */ - AST_ADD, - /** Subtract, \c - */ - AST_SUB, - /** Multiply, \ * */ - AST_MUL, - /** Divide, \c \ */ - AST_DIV, - /** Remainder, \c % */ - AST_REM, - /** Logical and, \c && */ - AST_LAND, - /** Logical or, \c ||*/ - AST_LOR, - /** Left shift (logical), \c << @todo add arithmetic shifts? */ - AST_LSHIFT, - /** Right shift (logical), \c >> */ - AST_RSHIFT, - /** Assigning add, \c += */ - AST_ASSIGN_ADD, - /** Assigning subtraction, \c -= */ - AST_ASSIGN_SUB, - /** Assigning multiplication, \c *= */ - AST_ASSIGN_MUL, - /** Assigning division, \c /= */ - AST_ASSIGN_DIV, - /** Assigning remainder, \c %= */ - AST_ASSIGN_REM, - /** Assigning logical left shift, \c >>= */ - AST_ASSIGN_LSHIFT, - /** Assigning logical right shift, \c <<= */ - AST_ASSIGN_RSHIFT, - /** Less than, \c < */ - AST_LT, - /** Greater than, \c > */ - AST_GT, - /** Less than or equal, \c <= */ - AST_LE, - /** Greater than or equal, \c >= */ - AST_GE, - /** Not equal, \c != */ - AST_NE, - /** Equal, \c == */ - AST_EQ, -}; - -/** Unary operations, that is they take one argument and produce a result. */ -enum ast_unops { - /** Negation, \c - */ - AST_NEG, - /** Logical negation, \c ! */ - AST_LNOT, - /** Referencing, \c & */ - AST_REF, - /** Dereferencing, \c ' */ - AST_DEREF, -}; - #define NULL_LOC() ((struct src_loc){0, 0, 0, 0}) /** Represents a source location, spanning over some bit of code. */ @@ -139,20 +28,16 @@ struct src_loc { }; /** Possible AST node types. We reserve node 0 as an illegal value. */ -enum ast_node_type { - /** Binary operation. */ - AST_BINOP = 1, - /** Unary operation. */ - AST_UNOP, +enum ast_kind { /** Fetch enum constant. */ - AST_FETCH, + AST_FETCH = 1, /** Value initialization. */ AST_INIT, /** Assignment. */ AST_ASSIGN, /** Call procedure. */ AST_CALL, - AST_ARR_ACCESS, + AST_ARR, /** Sizeof. */ AST_SIZEOF, /** Cast. */ @@ -160,17 +45,17 @@ enum ast_node_type { /** Defer. */ AST_DEFER, /** Macro definition. */ - AST_MACRO_CONSTRUCT, + AST_MACRO_DEF, AST_MACRO_EXPAND, AST_TYPE_EXPAND, /** Procedure definition. */ - AST_PROC, + AST_PROC_DEF, /** Goto. */ AST_GOTO, /** Goto label. */ AST_LABEL, /** Variable declaration/definition. */ - AST_VAR, + AST_VAR_DEF, /** For loop. */ AST_FOR, /** Embed file contents. */ @@ -182,88 +67,99 @@ enum ast_node_type { * \c AST_DELAYED is active for \c do loops. */ AST_WHILE, + AST_DO_WHILE, /** Control statement, \c break or \c continue. */ - AST_CTRL, + AST_BREAK, + AST_CONTINUE, /** Return. */ AST_RETURN, /** Alias definition. */ - AST_ALIAS, + AST_ALIAS_DEF, /** More like trait. @todo really come up with consistent naming. */ - AST_TRAIT, + AST_TRAIT_DEF, /** Structure definition. */ - AST_STRUCT, + AST_STRUCT_DEF, /** If. */ AST_IF, - /** Special 'meta' node that represents a type. */ - AST_TYPE, /** Block. E.g. \c {} */ AST_BLOCK, /** Import. */ AST_IMPORT, /** Enum definition. */ - AST_ENUM, + AST_ENUM_DEF, /** Enum constant value. */ AST_VAL, /** Switch. */ AST_SWITCH, /** Switch case. */ AST_CASE, - /** Constant value. */ - AST_CONST, /** Any ID, variable or whatever. */ AST_ID, /** As statement, used to determine types. */ AST_AS, /** Empty. Essentially noop. */ AST_EMPTY, -}; - -/** Whether \c AST_CTRL is break or continue. */ -enum ast_ctrl_kind { - /** Break. */ - AST_CTRL_BREAK, - /** Continue. */ - AST_CTRL_CONTINUE -}; - -/** Constant value kind. */ -enum ast_const_kind { - /** Integer, i27 */ - AST_CONST_INTEGER, - /** String. */ - AST_CONST_STRING, -}; - -/** Type representation. */ -enum ast_type_kind { - /** ID, can refer to pretty much anything. */ - AST_TYPE_ID, - AST_TYPE_PRIMITIVE, - /** Array. */ - AST_TYPE_ARR, - AST_TYPE_CONSTRUCT, - /** Trait. */ - AST_TYPE_TRAIT, - /** Pointer to a type. */ - AST_TYPE_POINTER, - /** Structure. */ - AST_TYPE_STRUCT, - /** Enum. */ - AST_TYPE_ENUM, - /** Signature, i.e. procedure signature. */ - AST_TYPE_SIGN, -}; - -/** Whether typedef makes an alias on trait. */ -enum ast_typedef_kind { - /** Alias. */ - AST_TYPEDEF_ALIAS, - /** Trait. */ - AST_TYPEDEF_TRAIT, + /** Add, \c + */ + AST_ADD, + /** Subtract, \c - */ + AST_SUB, + /** Multiply, \ * */ + AST_MUL, + /** Divide, \c \ */ + AST_DIV, + /** Remainder, \c % */ + AST_REM, + /** Logical and, \c && */ + AST_LAND, + /** Logical or, \c ||*/ + AST_LOR, + /** Left shift (logical), \c << @todo add arithmetic shifts? */ + AST_LSHIFT, + /** Right shift (logical), \c >> */ + AST_RSHIFT, + /** Assigning add, \c += */ + AST_ASSIGN_ADD, + /** Assigning subtraction, \c -= */ + AST_ASSIGN_SUB, + /** Assigning multiplication, \c *= */ + AST_ASSIGN_MUL, + /** Assigning division, \c /= */ + AST_ASSIGN_DIV, + /** Assigning remainder, \c %= */ + AST_ASSIGN_REM, + /** Assigning logical left shift, \c >>= */ + AST_ASSIGN_LSHIFT, + /** Assigning logical right shift, \c <<= */ + AST_ASSIGN_RSHIFT, + /** Less than, \c < */ + AST_LT, + /** Greater than, \c > */ + AST_GT, + /** Less than or equal, \c <= */ + AST_LE, + /** Greater than or equal, \c >= */ + AST_GE, + /** Not equal, \c != */ + AST_NE, + /** Equal, \c == */ + AST_EQ, + /** Negation, \c - */ + AST_NEG, + /** Logical negation, \c ! */ + AST_LNOT, + AST_NOT, + /** Referencing, \c & */ + AST_REF, + /** Dereferencing, \c ' */ + AST_DEREF, + AST_CONST_INT, + AST_CONST_CHAR, + AST_CONST_BOOL, + AST_CONST_STR, }; /** Flags an AST node can have. */ -enum ast_flag { +enum ast_flags { /** Node is mutable. Mostly used for variables. */ AST_FLAG_MUTABLE = (1 << 0), /** Value is constant. Constant if, for, etc. */ @@ -300,1005 +196,461 @@ enum ast_flag { AST_FLAG_DOEXPR = (1 << 15), }; -struct ast_node; - -/** - * AST if node. - * - * \verbatim - * if cond {body} [els] - * \endverbatim - */ -struct ast_if { - /** Conditional block. */ - struct ast_node *cond; - /** Body. */ - struct ast_node *body; - /** Else block. */ - struct ast_node *els; -}; - -/** AST fetch enum member node. */ -struct ast_fetch { - /** Name of member to fetch. */ - struct ast_node *id; - /** Enum type to fetch from. */ - struct ast_node *type; -}; - -/** Goto label. */ -struct ast_label { - /** Label name. */ - struct ast_node *id; - /** - * List of active defers. - * Used to determine which defer statements should be executed - * when a goto jumps to this 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. */ - struct ast_node *label; - /** - * List of active defers. - * With the list in the corresponding label, we can detect which - * defers should be triggered and which ones shouldn't. - * See actualize_goto_defers(). - */ - struct ast_node *defers; -}; - -/** Alias definition. */ -struct ast_alias { - /** Name of alias. */ - struct ast_node *id; - /** Type to alias. */ - struct ast_node *type; -}; - -/** List of types that implements the template list belongs to. */ -struct trait_implemented { - /** A type that implements the template. */ - struct ast_node *type; - /** Next type that implements the template. */ - struct trait_implemented *next; -}; - -/** A trait definition. */ -struct ast_trait { - /** Name of trait. */ - struct ast_node *id; - /** Parameters to construct concrete type from trait. */ - struct ast_node *params; - /** Raw body before expansion. */ - struct ast_node *raw_body; - /** Body of trait. */ - struct ast_node *body; -}; +struct ast; -/** Cast. */ -struct ast_cast { - /** Expression. */ - struct ast_node *expr; - /** Type to cast expression result to. */ - struct ast_node *type; +enum type_kind { + TYPE_VOID = 1, TYPE_BOOL, TYPE_I9, TYPE_I27, TYPE_STR, TYPE_PTR, + TYPE_ID, TYPE_CONSTRUCT, TYPE_STRUCT, TYPE_ENUM, TYPE_CALLABLE, + TYPE_TRAIT, }; -/** Binary operation. */ -struct ast_binop { - /** Which operation. */ - enum ast_binops op; - /** Left operand. */ - struct ast_node *left; - /** Right operand. */ - struct ast_node *right; -}; - -/** Unary operation. */ -struct ast_unop { - /** Which operation. */ - enum ast_unops op; - /** Expression. */ - struct ast_node *expr; -}; +struct type { + enum type_kind k; -/** A call. */ -struct ast_call { - /** Name to call, whatever it may be. */ - struct ast_node *expr; - /** List of arguments to call. */ - struct ast_node *args; -}; - -/** Defer. */ -struct ast_defer { - /** Expression to defer. */ - struct ast_node *expr; -}; + /* arg */ + struct type *t0; + struct type *t1; -/** Macro definition. */ -struct ast_macro_construct { - /** Name of macro. */ - struct ast_node *id; - /** Parameters macro takes. */ - struct ast_node *params; - /** Macro body. */ - struct ast_node *body; -}; - -struct ast_macro_expand { - struct ast_node *id; - struct ast_node *args; -}; - -struct ast_type_expand { - struct ast_node *id; - struct ast_node *args; -}; + /* definition */ + struct ast *d; + /* alias */ + struct ast *a; + /* id */ + char *id; + /* next */ + struct type *n; -/** Procedure definition. */ -struct ast_proc { - /** Procedure name. */ - struct ast_node *id; - /** Procedure signature. */ - struct ast_node *sign; - /** Procedure body. */ - struct ast_node *body; -}; - -/** Dot. */ -struct ast_dot { - /** Expression to do dot operation on. */ - struct ast_node *expr; - /** Name to dot. */ - struct ast_node *id; -}; - -/** As. */ -struct ast_as { - /** Type to use for resolution. */ - struct ast_node *type; -}; - -/** Sizeof. */ -struct ast_sizeof { - /** Expression to get type of. */ - struct ast_node *expr; -}; - -/** Variable declaration. */ -struct ast_var { - /** Name of variable. */ - struct ast_node *id; - /** Type of variable. */ - struct ast_node *type; - /** Initialization expression. */ - struct ast_node *init; -}; - -/** Lambda definition. */ -struct ast_lambda { - /** Which variables to capture from the context. */ - struct ast_node *captures; - /** Signature of lambda. */ - struct ast_node *sign; - /** Body of lambda. */ - struct ast_node *body; -}; - -/** - * For loop. - * - * \verbatim - * for (pre; cond; post) {body} - * \endverbatim - */ -struct ast_for { - /** Initialization. */ - struct ast_node *pre; - /** Condition. */ - struct ast_node *cond; - /** Iteration. */ - struct ast_node *post; - /** Body. */ - struct ast_node *body; + struct src_loc loc; + struct scope *scope; }; -/** While loop. */ -struct ast_while { - /** Condition. */ - struct ast_node *cond; - /** Body. */ - struct ast_node *body; -}; +struct ast { + enum ast_kind k; + struct type *t; + long long v; + char *s; + struct ast *a0; + struct ast *a1; + struct ast *a2; + struct ast *a3; + struct type *t2; + enum ast_flags f; -/** Control. */ -struct ast_ctrl { - /** Break or continue. */ - enum ast_ctrl_kind kind; - /** - * List of active defers. - * Similarly to goto, used to figure out which defers to trigger. - */ - struct ast_node *defers; -}; + struct ast *n; + long long uses; -/** Return. */ -struct ast_return { - /** Expression to return. */ - struct ast_node *expr; - /** List of active defers. */ - struct ast_node *defers; + struct src_loc loc; + struct scope *scope; }; -enum ast_primitive { - AST_VOID, AST_BOOL, AST_I9, AST_I27, AST_STR -}; +struct ast *gen_ast(enum ast_kind kind, + struct ast *a0, + struct ast *a1, + struct ast *a2, + struct ast *a3, + struct type *t1, + char *s, + long long v, + struct src_loc loc); -/** - * Type. - * I'm not entirely happy with the current type system, for one - * some parts are only used until they get initialized, which makes it - * sort of difficult to follow what each kind means. - * - * @todo Could be better to have separate type nodes instead of co-opting - * AST nodes. - */ -struct ast_type { - /** Type kind. */ - enum ast_type_kind kind; - /** - * 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; - struct ast_node *as; - struct ast_node *aliased; +struct type *tgen_type(enum type_kind kind, + struct type *t0, + struct type *t1, + struct ast *d, + struct ast *a, + char *id, + struct src_loc loc); - /** Data relevant to kind. */ - union { - /** Name of a type, to be converted later. */ - struct { - struct ast_node *id; - } _id; +#define tgen_primitive(kind, id, def, loc)\ + tgen_type(kind, NULL, NULL, def, NULL, id, loc) - struct { - struct ast_node *id; - struct ast_node *args; - } _construct; +#define tgen_id(id, loc)\ + tgen_type(TYPE_ID, NULL, NULL, NULL, NULL, id, loc) - struct { - enum ast_primitive type; - struct ast_node *def; // for possible user defined - // member functions - } _primitive; +#define tgen_struct(id, def, loc)\ + tgen_type(TYPE_STRUCT, NULL, NULL, def, NULL, id, loc) - /** Array type. */ - struct { - struct ast_node *size; - struct ast_node *base; - } _arr; +#define tgen_trait(id, def, loc)\ + tgen_type(TYPE_TRAIT, NULL, NULL, def, NULL, id, loc) - struct { - struct ast_node *base; - } _ptr; +static inline bool is_binop(struct ast *x) +{ + switch (x->k) { + case AST_ADD: + case AST_SUB: + case AST_MUL: + case AST_DIV: + case AST_REM: + case AST_LSHIFT: + case AST_RSHIFT: + return true; + default: + }; - /** Procedure. */ - struct { - /** Name. */ - struct ast_node *id; - /** Parameters. */ - struct ast_node *params; - /** Return type. */ - struct ast_node *ret; - } _proc; + return false; +} - /** Trait. */ - struct { - /** Trait definition. */ - struct ast_node *def; - } _trait; +static inline bool is_opassign(struct ast *x) +{ + switch (x->k) { + case AST_ASSIGN_ADD: + case AST_ASSIGN_SUB: + case AST_ASSIGN_MUL: + case AST_ASSIGN_DIV: + case AST_ASSIGN_REM: + case AST_ASSIGN_LSHIFT: + case AST_ASSIGN_RSHIFT: + return true; + default: + }; + return false; +} - /** Structure. */ - struct { - /** Structure definition. */ - struct ast_node *def; - } _struct; +static inline bool is_unop(struct ast *x) +{ + switch (x->k) { + case AST_REF: + case AST_DEREF: + case AST_NOT: + case AST_NEG: + return true; + default: + } - /** Enumeration. */ - struct { - /** Enum definition. */ - struct ast_node *def; - } _enum; + return false; +} - /** Union. */ - struct { - /** Name of union. */ - struct ast_node *id; - /** Arguments for type parameters. */ - struct ast_node *impls; - } _union; +static inline bool is_comparison(struct ast *x) +{ + switch (x->k) { + case AST_LT: + case AST_GT: + case AST_LE: + case AST_GE: + case AST_NE: + case AST_EQ: + return true; + default: + } - struct { - /** Parameter types. */ - struct ast_node *params; - /** Return type. */ - struct ast_node *ret; - } _sign; - }; -}; + return false; +} -/** Block. */ -struct ast_block { - /** Body of block. */ - struct ast_node *body; - /** List of defers. */ - struct ast_node *defers; -}; +static inline bool is_const(struct ast *x) +{ + /* note that const strings are sort of their own entity */ + switch (x->k) { + case AST_CONST_INT: + case AST_CONST_CHAR: + case AST_CONST_BOOL: + return true; + default: + } -/** Import. */ -struct ast_import { - /** File to import. */ - const char *file; -}; + return false; +} -/** Embed. @todo figure out how embedding should be done, just *u8? */ -struct ast_embed { - /** File to embed. */ - const char *file; -}; +static inline bool is_primitive(struct type *t) +{ + switch (t->k) { + case TYPE_I27: + case TYPE_I9: + case TYPE_BOOL: + case TYPE_PTR: + return true; + default: + } -/** Enum definition. */ -struct ast_enum { - /** Name of enum. */ - struct ast_node *id; - /** Type enum is convertible to/from. */ - struct ast_node *type; - /** Body. */ - struct ast_node *body; -}; + return false; +} -/** Structure definition. */ -struct ast_struct { - /** Name of structure. */ - struct ast_node *id; - /** List of type parameters, if any. */ - struct ast_node *generics; - /** Body. */ - struct ast_node *body; - struct trait_implemented *implemented_by; -}; +#define gen_str_type1(k, s, t, a, loc) gen_ast(k, a, NULL, NULL, NULL, t, s, 0, loc) +#define gen_str_type(k, s, t, loc) gen_str_type1(k, s, t, NULL, loc) +#define gen_type(k, a, type, loc) gen_ast(k, a, NULL, NULL, NULL, type, NULL, 0, loc) +#define gen_str2(k, s, a, b, loc) gen_ast(k, a, b, NULL, NULL, NULL, s, 0, loc) +#define gen_str1(k, s, a, loc) gen_str2(k, s, a, NULL, loc) +#define gen_str(k, s, loc) gen_ast(k, NULL, NULL, NULL, NULL, NULL, s, 0, loc) -/** Enum member constant value. */ -struct ast_val { - /** Name of member. */ - struct ast_node *id; - /** Constant value of member. */ - struct ast_node *val; -}; -/** Switch. */ -struct ast_switch { - /** Condition. */ - struct ast_node *cond; - /** List of cases. */ - struct ast_node *cases; -}; +#define gen4(k, a, b, c, d, loc) gen_ast(k, a, b, c, d, NULL, NULL, 0, loc) +#define gen3(k, a, b, c, loc) gen4(k, a, b, c, NULL, loc) +#define gen2(k, a, b, loc) gen3(k, a, b, NULL, loc) +#define gen1(k, a, loc) gen2(k, a, NULL, loc) -/** Switch case. */ -struct ast_case { - /** Condition. */ - struct ast_node *cond; - /** Body. */ - struct ast_node *body; -}; +#define tgen2(k, a, b, loc) tgen_type(k, a, b, NULL, NULL, NULL, loc) +#define tgen1(k, a, loc) tgen2(k, a, NULL, loc) -/** Constant value. */ -struct ast_const { - /** Constant kind. */ - enum ast_const_kind kind; - union { - /** Integer. */ - long long integer; - /** String. */ - const char *str; - }; -}; +#define tgen_str1(k, s, a, loc) tgen_type(k, a, NULL, NULL, NULL, s, loc) -/** Value initialization. */ -struct ast_init { - /** Body. @todo maybe come up with a better name? */ - struct ast_node *body; -}; +/* kind of hacky but I guess it works, and allows us to check that the type is + * correct every time */ +#define return_s(x, kind) *({assert((x)->k == kind); &(x)->s;}) +#define return_a0(x, kind) *({assert((x)->k == kind); &(x)->a0;}) +#define return_a1(x, kind) *({assert((x)->k == kind); &(x)->a1;}) +#define return_a2(x, kind) *({assert((x)->k == kind); &(x)->a2;}) +#define return_a3(x, kind) *({assert((x)->k == kind); &(x)->a3;}) -/** Assignment. */ -struct ast_assign { - /** Where to assign to. */ - struct ast_node *to; - /** What to assign from. */ - struct ast_node *from; -}; +#define return_t0(x, kind) *({assert((x)->k == kind); &(x)->t0;}) +#define return_t1(x, kind) *({assert((x)->k == kind); &(x)->t1;}) +/* note that this one is in ast, the other two are in type */ +#define return_t2(x, kind) *({assert((x)->k == kind); &(x)->t2;}) -/** - * An ID. - * @todo One optimization would be to reduce number of ast_ids, - * replacing them with raw strings. - */ -struct ast_id { - /** Actual ID. */ - const char *id; -}; +#define if_cond(x) return_a0(x, AST_IF) +#define if_body(x) return_a1(x, AST_IF) +#define if_else(x) return_a2(x, AST_IF) +#define gen_if(cond, body, else, loc)\ + gen3(AST_IF, cond, body, else, loc) -/** Empty node. */ -struct ast_empty { -}; +#define fetch_id(x) return_s(x, AST_FETCH) +#define fetch_type(x) return_t2(x, AST_FETCH) +#define gen_fetch(id, type, loc)\ + gen_str_type(AST_FETCH, id, type, loc) -/** AST node. */ -struct ast_node { - /** Node type. */ - enum ast_node_type node_type; - /** Node flags. */ - enum ast_flag flags; - /** Next node, when applicable. I.e. body statements. */ - struct ast_node *next; - /** Source location. */ - struct src_loc loc; - /** Scope node belongs to. */ - struct scope *scope; - /** Ek type. */ - struct ast_node *type; +#define label_id(x) return_s(x, AST_LABEL) +#define label_defers(x) return_a0(x, AST_LABEL) +#define gen_label(id, defers, loc)\ + gen_str1(AST_LABEL, id, defers, loc) - size_t uses; +#define arr_base(x) return_a0(x, AST_ARR) +#define arr_idx(x) return_a1(x, AST_ARR) +#define gen_arr(base, idx, loc)\ + gen2(AST_ARR, base, idx, loc) - /** Data relevant to kind. */ - union { - struct ast_arr_access _arr_access; - /** Binary operation. */ - struct ast_binop _binop; - /** Unary operation. */ - struct ast_unop _unop; - /** Call. */ - struct ast_call _call; - /** Cast. */ - struct ast_cast _cast; - /** Macro definition. */ - struct ast_macro_construct _macro_construct; - struct ast_macro_expand _macro_expand; - struct ast_type_expand _type_expand; - /** Procedure definition. */ - struct ast_proc _proc; - /** Goto. */ - struct ast_goto _goto; - /** Goto label. */ - struct ast_label _label; - /** Variable. */ - struct ast_var _var; - /** Lambda. */ - struct ast_lambda _lambda; - /** If. */ - struct ast_if _if; - /** For. */ - struct ast_for _for; - /** While. */ - struct ast_while _while; - /** Break/continue. */ - struct ast_ctrl _ctrl; - /** Defer. */ - struct ast_defer _defer; - /** Type. */ - struct ast_type _type; - /** Dot. */ - struct ast_dot _dot; - /** Block. */ - struct ast_block _block; - /** Import. */ - struct ast_import _import; - /** Embed. */ - struct ast_embed _embed; - /** Return. */ - struct ast_return _return; - /** Switch. */ - struct ast_switch _switch; - /** Alias. */ - struct ast_alias _alias; - /** Trait definition. */ - struct ast_trait _trait; - /** Enum definition. */ - struct ast_enum _enum; - /** Structure definition. */ - struct ast_struct _struct; - /** Enum value. */ - struct ast_val _val; - /** Switch case. */ - struct ast_case _case; - /** Constant value. */ - struct ast_const _const; - /** Initialization. */ - struct ast_init _init; - /** Assignment. */ - struct ast_assign _assign; - /** ID. */ - struct ast_id _id; - /** As type. */ - struct ast_as _as; - /** Sizeof. */ - struct ast_sizeof _sizeof; - /** Fetch enum member. */ - struct ast_fetch _fetch; - /** Empty. */ - struct ast_empty _empty; - }; -}; +#define goto_label(x) return_s(x, AST_GOTO) +#define goto_defers(x) return_a0(x, AST_GOTO) +#define gen_goto(label, defers, loc)\ + gen_str1(AST_GOTO, label, defers, loc) -struct ast_node *gen_arr_access(struct ast_node *base, struct ast_node *idx, - struct src_loc loc); +#define alias_id(x) return_s(x, AST_ALIAS_DEF) +#define alias_type(x) return_t2(x, AST_ALIAS_DEF) +#define gen_alias(id, type, loc)\ + gen_str_type(AST_ALIAS_DEF, id, type, loc) -/** - * Generate binary operation node. - * - * @param op Which operation. - * @param left Left operand. - * @param right Right operand. - * @return Corresponding AST node. - */ -struct ast_node *gen_binop(enum ast_binops op, - struct ast_node *left, - struct ast_node *right, - struct src_loc loc); +#define trait_id(x) return_s(x, AST_TRAIT_DEF) +#define trait_params(x) return_a0(x, AST_TRAIT_DEF) +#define trait_raw_body(x) return_a1(x, AST_TRAIT_DEF) +#define trait_body(x) return_a2(x, AST_TRAIT_DEF) +#define gen_trait(id, params, body, loc)\ + gen_str2(AST_TRAIT_DEF, id, params, body, loc) -/** - * Generate unary operation. - * - * @param op Which operation. - * @param expr Expression. - * @return Corresponding AST node. - */ -struct ast_node *gen_unop(enum ast_unops op, struct ast_node *expr, - struct src_loc loc); +#define cast_expr(x) return_a0(x, AST_CAST) +#define cast_type(x) return_t2(x, AST_CAST) +#define gen_cast(expr, type, loc)\ + gen_type(AST_CAST, expr, type, loc) -/** - * Generate call. - * - * @param id ID to call. - * @param args Arguments to call. - * @return Corresponding AST node. - */ -struct ast_node *gen_call(struct ast_node *id, struct ast_node *args, - struct src_loc loc); +#define opassign_left(x) ({assert(is_opassign(x)); x->a0;}) +#define opassign_right(x) ({assert(is_opassign(x)); x->a1;}) +#define gen_opassign(op, left, right, loc)\ + gen2(op, left, right, loc) -/** - * Generate ID. - * - * @param id ID. - * @return Corresponding AST node. - */ -struct ast_node *gen_id(const char *id, struct src_loc loc); +#define binop_left(x) ({assert(is_binop(x)); x->a0;}) +#define binop_right(x) ({assert(is_binop(x)); x->a1;}) +#define gen_binop(op, left, right, loc)\ + gen2(op, left, right, loc) -/** - * Generate constant integer. - * - * @param integer Integer. - * @return Corresponding AST node. - */ -struct ast_node *gen_int(long long integer, struct src_loc loc); +#define comparison_left(x) ({assert(is_comparison(x)); x->a0;}) +#define comparison_right(x) ({assert(is_comparison(x)); x->a1;}) +#define gen_comparison(op, left, right, loc)\ + gen2(op, left, right, loc) -/** - * Generate constant string. - * - * @param str String. - * @return Corresponding AST node. - */ -struct ast_node *gen_string(const char *str, struct src_loc loc); +#define unop_expr(x) ({assert(is_unop(x)); x->a0;}) +#define gen_unop(op, expr, loc)\ + gen1(op, expr, loc) -/** - * Generate constant float. - * - * @param dbl Double. - * @return Corresponding AST node. - */ -struct ast_node *gen_float(double dbl, struct src_loc loc); +#define call_expr(x) return_a0(x, AST_CALL) +#define call_args(x) return_a1(x, AST_CALL) +#define gen_call(expr, args, loc)\ + gen2(AST_CALL, expr, args, loc) -/** - * Generate assignment. - * - * @param to Where to assign to. - * @param from Where to assign from. - * @return Corresponding AST node. - */ -struct ast_node *gen_assign(struct ast_node *to, struct ast_node *from, - struct src_loc loc); +#define defer_expr(x) return_a0(x, AST_DEFER) +#define gen_defer(expr, loc)\ + gen1(AST_DEFER, expr, loc) -/** - * Generate initialization. - * - * @param body Body of initialization. - * @return Corresponding AST node. - */ -struct ast_node *gen_init(struct ast_node *body, struct src_loc loc); +#define macro_def_id(x) return_s(x, AST_MACRO_DEF) +#define macro_def_params(x) return_a0(x, AST_MACRO_DEF) +#define macro_def_body(x) return_a1(x, AST_MACRO_DEF) +#define gen_macro_def(id, params, body, loc)\ + gen_str2(AST_MACRO_DEF, id, params, body, loc) -/** - * Generate while loop. - * - * @param cond Condition. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_while(struct ast_node *cond, struct ast_node *body, - struct src_loc loc); +#define macro_expand_id(x) return_s(x, AST_MACRO_EXPAND) +#define macro_expand_args(x) return_a0(x, AST_MACRO_EXPAND) +#define gen_macro_expand(id, args, loc)\ + gen_str1(AST_MACRO_EXPAND, id, args, loc) -/** - * Generate for loop. - * - * @param pre Pre condition. - * @param cond Condition. - * @param post Post condition. - * @param body Loop body. - * @return Corresponding AST node. - */ -struct ast_node *gen_for(struct ast_node *pre, struct ast_node *cond, - struct ast_node *post, struct ast_node *body, - struct src_loc loc); +#define type_expand_id(x) return_s(x, AST_TYPE_EXPAND) +#define type_expand_args(x) return_t2(x, AST_TYPE_EXPAND) +#define gen_type_expand(id, args, loc)\ + gen_str_type(AST_TYPE_EXPAND, id, args, loc) -/** - * Generate return. - * - * @param expr Expression. - * @return Corresponding AST node. - */ -struct ast_node *gen_return(struct ast_node *expr, struct src_loc loc); +#define proc_id(x) return_s(x, AST_PROC_DEF) +#define proc_params(x) return_a0(x, AST_PROC_DEF) +#define proc_rtype(x) return_t2(x, AST_PROC_DEF) +#define proc_body(x) return_a1(x, AST_PROC_DEF) +#define gen_proc(id, params, rtype, body, loc)\ + gen_ast(AST_PROC_DEF, params, body, NULL, NULL, rtype, id, 0, loc) -/** - * Generate control statement. - * @note Some generators take source location info, which is then - * propagated to higher level nodes. - * - * @todo not sure where to best place the note about location - * - * @param kind Break or continue. - * @param loc Source location. - * @return Corresponding AST node. - */ -struct ast_node *gen_ctrl(enum ast_ctrl_kind kind, struct src_loc loc); +#define dot_id(x) return_s(x, AST_DOT) +#define dot_expr(x) return_a0(x, AST_DOT) +#define gen_dot(id, expr, loc)\ + gen_str1(AST_DOT, id, expr, loc) -/** - * Generate macro definition. - * - * @param id Macro name. - * @param params Macro parameters. - * @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 src_loc loc); +#define as_type(x) return_t2(x, AST_AS) +#define gen_as(type, loc)\ + gen_type(NULL, type, loc) -struct ast_node *gen_macro_expand(struct ast_node *id, struct ast_node *args, - struct src_loc loc); +#define sizeof_expr(x) return_a0(x, AST_SIZEOF) +#define gen_sizeof(expr, loc)\ + gen1(AST_SIZEOF, expr, 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); +#define var_id(x) return_s(x, AST_VAR_DEF) +#define var_type(x) return_t2(x, AST_VAR_DEF) +#define var_init(x) return_a0(x, AST_VAR_DEF) +#define gen_var(id, type, init, loc)\ + gen_ast(AST_VAR_DEF, init, NULL, NULL, NULL, type, id, 1, loc) -/** - * Generate if. - * - * @param cond Condition. - * @param body Body. - * @param els Else. - * @return Corresponding AST node. - */ -struct ast_node *gen_if(struct ast_node *cond, struct ast_node *body, - struct ast_node *els, struct src_loc loc); +#define for_pre(x) return_a0(x, AST_FOR) +#define for_cond(x) return_a1(x, AST_FOR) +#define for_post(x) return_a2(x, AST_FOR) +#define for_body(x) return_a3(x, AST_FOR) +#define gen_for(pre, cond, post, body, loc)\ + gen4(AST_FOR, pre, cond, post, body, loc) -/** - * Generate switch. - * - * @param cond Condition. - * @param cases List of cases. - * @return Corresponding AST node. - */ -struct ast_node *gen_switch(struct ast_node *cond, struct ast_node *cases, - struct src_loc loc); +#define while_cond(x) return_a0(x, AST_WHILE) +#define while_body(x) return_a1(x, AST_WHILE) +#define gen_while(cond, body, loc)\ + gen2(AST_WHILE, cond, body, loc) -/** - * Generate switch case. - * - * @param expr Condition. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_case(struct ast_node *expr, struct ast_node *body, - struct src_loc loc); +#define do_while_cond(x) return_a0(x, AST_DO_WHILE) +#define do_while_body(x) return_a1(x, AST_DO_WHILE) +#define gen_do_while(cond, body, loc)\ + gen2(AST_DO_WHILE, cond, body, loc) -struct ast_node *gen_primitive(enum ast_primitive type, struct ast_node *def, - struct src_loc loc); -/** - * Generate Ek type (besides primitive). - * - * @param kind Type kind. - * @param id Name of type. - * @param decl List of parameters, when applicable. - * @param rets Return type, when applicable. - * @return Corresponding AST node. - */ -struct ast_node *gen_type(enum ast_type_kind kind, struct ast_node *t2, - struct ast_node *t1, - struct src_loc loc); +#define continue_defers(x) return_a0(x, AST_CONTINUE) +#define gen_continue(defers, loc)\ + gen1(AST_CONTINUE, defers, loc) -/** - * Generate block. - * - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_block(struct ast_node *body, struct src_loc loc); +#define break_defers(x) return_a0(x, AST_BREAK) +#define gen_break(defers, loc)\ + gen1(AST_BREAK, defers, loc) -/** - * Generate variable. - * - * @param id Name of variable. - * @param type Type of varibable. - * @param init Initialization, when applicable. - * @return Corresponding AST node. - */ -struct ast_node *gen_var(struct ast_node *id, struct ast_node *type, - struct ast_node *init, struct src_loc loc); +#define return_expr(x) return_a0(x, AST_RETURN) +#define return_defers(x) return_a1(x, AST_RETURN) +#define gen_return(expr, defers, loc)\ + gen2(AST_RETURN, expr, defers, loc) -/** - * Generate lambda. - * - * @param captures List of captures. - * @param type Signature of lambda. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_lambda(struct ast_node *captures, - struct ast_node *type, struct ast_node *body, - struct src_loc loc); +#define block_body(x) return_a0(x, AST_BLOCK) +#define block_defers(x) return_a1(x, AST_BLOCK) +#define gen_block(body, defers, loc)\ + gen2(AST_BLOCK, body, defers, loc) -/** - * Generate procedure definition. - * - * @param id Name of procedure. - * @param type Signature of procedure. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_proc(struct ast_node *id, struct ast_node *type, - struct ast_node *body, struct src_loc loc); +#define import_file(x) return_s(x, AST_IMPORT) +#define gen_import(f, loc)\ + gen_str(AST_IMPORT, f, loc) -/** - * Generate dot operation. - * - * @param expr Expression to do dot operation to. - * @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 src_loc loc); +#define embed_file(x) return_s(x, AST_EMBED) +#define gen_embed(f, loc)\ + gen_str(AST_EMBED, f, loc) -/** - * Generate enum definition. - * - * @param id Name of enumeration type. - * @param type Type of enum. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_enum(struct ast_node *id, struct ast_node *type, - struct ast_node *body, struct src_loc loc); +#define enum_id(x) return_s(x, AST_ENUM_DEF) +#define enum_type(x) return_t2(x, AST_ENUM_DEF) +#define enum_body(x) return_a0(x, AST_ENUM_DEF) +#define gen_enum(id, type, body, loc)\ + gen_ast(AST_ENUM_DEF, body, NULL, NULL, NULL, type, id, 0, loc) -/** - * Generate enum member value. - * - * @param id Name of enumeration member. - * @param val Value of enumeration member. - * @return Corresponding AST node. - */ -struct ast_node *gen_val(struct ast_node *id, struct ast_node *val, - struct src_loc loc); +#define struct_id(x) return_s(x, AST_STRUCT_DEF) +#define struct_params(x) return_a0(x, AST_STRUCT_DEF) +#define struct_body(x) return_a1(x, AST_STRUCT_DEF) +#define gen_struct(id, params, body, loc)\ + gen_str2(AST_STRUCT_DEF, id, params, body, loc) -/** - * Generate alias definition. - * - * @param id Name of alias. - * @param type Type to alias. - * @return Corresponding AST node. - */ -struct ast_node *gen_alias(struct ast_node *id, struct ast_node *type, - struct src_loc loc); +#define val_id(x) return_s(x, AST_VAL) +#define val_val(x) return_a0(x, AST_VAL) +#define gen_val(id, val, loc)\ + gen_str1(AST_VAL, id, val, loc) -/** - * Generate trait definition. - * - * @param id Name of trait. - * @param body Body. - * @return Corresponding AST node. - */ -struct ast_node *gen_trait(struct ast_node *id, struct ast_node *params, - struct ast_node *raw_body, struct ast_node *body, - struct src_loc loc); +#define switch_cond(x) return_a0(x, AST_SWITCH) +#define switch_cases(x) return_a1(x, AST_SWITCH) +#define gen_switch(cond, cases, loc)\ + gen2(AST_SWITCH, cond, cases, loc) -/** - * Generate import; - * - * @param file File to import. - * @return Corresponding AST node. - */ -struct ast_node *gen_import(const char *file, struct src_loc loc); +#define case_cond(x) return_a0(x, AST_CASE) +#define case_body(x) return_a1(x, AST_CASE) +#define gen_case(cond, body, loc)\ + gen2(AST_CASE, cond, body, loc) -/** - * Generate cast. - * - * @param expr Expression. - * @param type Type to cast expression result to. - * @return Corresponding AST node. - */ -struct ast_node *gen_cast(struct ast_node *expr, struct ast_node *type, - struct src_loc loc); +#define str_val(x) return_s(x, AST_CONST_STR) +#define gen_const_str(s, loc)\ + gen_ast(AST_CONST_STR, NULL, NULL, NULL, NULL, NULL, s, 0, loc) -/** - * Generate embed. - * - * @param file File to embed. - * @return Corresponding AST node. - */ -struct ast_node *gen_embed(const char *file, struct src_loc loc); +#define int_val(x) *({assert(x->k == AST_CONST_INT); &x->v;}) +#define gen_const_int(i, loc)\ + gen_ast(AST_CONST_INT, NULL, NULL, NULL, NULL, NULL, NULL, i, loc) -/** - * Generate goto. - * - * @param label Name of label to jump to. - * @return Corresponding AST node. - */ -struct ast_node *gen_goto(struct ast_node *label, struct src_loc loc); +#define char_val(x) *({assert(x->k == AST_CONST_CHAR); &x->v;}) +#define gen_const_char(i, loc)\ + gen_ast(AST_CONST_CHAR, NULL, NULL, NULL, NULL, NULL, NULL, i, loc) -/** - * Generate goto label. - * - * @param id Name of label. - * @return Corresponding AST node. - */ -struct ast_node *gen_label(struct ast_node *id, struct src_loc loc); +#define bool_val(x) *({assert(x->k == AST_CONST_CHAR); &x->v;}) +#define gen_const_bool(i, loc)\ + gen_ast(AST_CONST_BOOL, NULL, NULL, NULL, NULL, NULL, NULL, i, loc) -/** - * Generate defer. - * - * @param expr Expression to defer. - * @return Corresponding AST node. - */ -struct ast_node *gen_defer(struct ast_node *expr, struct src_loc loc); +#define init_body(x) return_a0(x, AST_ASSIGN) +#define gen_init(body, loc)\ + gen1(AST_INIT, body, loc) -/** - * Generate as. - * - * @param type Type to resolve with. - * @return Corresponding AST node. - */ -struct ast_node *gen_as(struct ast_node *type, struct src_loc loc); +#define assign_to(x) return_a0(x, AST_ASSIGN) +#define assign_from(x) return_a1(x, AST_ASSIGN) +#define gen_assign(from, to, loc)\ + gen2(AST_ASSIGN, from, to, loc) -/** - * Generate sizeof. - * - * @param expr Expression to take type of. - * @return Corresponding AST node. - */ -struct ast_node *gen_sizeof(struct ast_node *expr, struct src_loc loc); +#define id_str(x) return_s(x, AST_ID) +#define gen_id(id, loc)\ + gen_str(AST_ID, id, loc) -/** - * Generate structure definition. - * - * @param id Name of structure. - * @param generics List of type parameters. - * @param body Body of structure. - * @return Corresponding AST node. - */ -struct ast_node *gen_struct(struct ast_node *id, struct ast_node *generics, - struct ast_node *body, struct src_loc loc); +#define gen_empty(loc)\ + gen1(AST_EMPTY, NULL, loc) -/** - * Generate enum member fetch. - * - * @param id Name of enum member to fetch. - * @param type Enum type to fetch from. - * @return Corresponding AST node. - */ -struct ast_node *gen_fetch(struct ast_node *id, struct ast_node *type, - struct src_loc loc); +/* types */ +#define callable_ptypes(x) return_t0(x, TYPE_CALLABLE) +#define callable_rtype(x) return_t0(x, TYPE_CALLABLE) +#define tgen_callable(ptypes, rtype, loc)\ + tgen2(TYPE_CALLABLE, ptypes, rtype, loc) -/** - * Generate empty AST node. - * - * @return Corresponding AST node. - */ -struct ast_node *gen_empty(); +#define ptr_base(x) return_t0(x, TYPE_PTR) +#define tgen_ptr(base, loc)\ + tgen1(TYPE_PTR, base, loc) -/** - * Clone AST node. - * - * @param node Node to clone. - * @return A clone of \p node. - */ -struct ast_node *clone_ast_node(struct ast_node *node); +#define construct_id(x) return_t0(x, TYPE_CONSTRUCT) +#define construct_atypes(x) return_t1(x, TYPE_CONSTRUCT) +#define tgen_construct(id, atypes, loc)\ + tgen_str1(TYPE_CONSTRUCT, id, atypes, loc) -/** - * Check if two nodes are identical. - * - * @param exact Ignore some less important checks, such as flags, location and - * scope. - * @param left One AST node to compare. - * @param right Other AST node to compare. - * @return \c 0 if nodes aren't identical, \c 1 otherwise. - */ -int identical_ast_nodes(int exact, struct ast_node *left, - struct ast_node *right); +struct ast *clone_ast(struct ast *n); +struct ast *clone_ast_list(struct ast *l); -/** - * Dump textual representation of AST to stdout. - * - * @param depth How many spaces to prepend. - * @param root AST node to dump. - */ -void dump_ast(int depth, struct ast_node *root); -void dump_ast_node(int depth, struct ast_node *node); +struct type *clone_type(struct type *n); +struct type *clone_type_list(struct type *l); -/** - * Add \p elem to end of \p list. - * - * @param list List of AST nodes. - * @param elem Add to end of \p list. - */ -void ast_append(struct ast_node *list, struct ast_node *elem); +void ast_dump_list(int depth, struct ast *root); +void ast_dump(int depth, struct ast *node); -/** - * Set AST node flags. - * - * @param node Node to set flags for. - * @param flags Flags to set. - */ -void ast_set_flags(struct ast_node *node, enum ast_flag flags); +void type_dump_list(struct type *root); +void type_dump(struct type *node); -/** - * Clear AST node flags. - * - * @param node Node to clear flags for. - * @param flags Flags to set. - */ -void ast_clear_flags(struct ast_node *node, enum ast_flag flags); +void ast_append(struct ast *list, struct ast *elem); +void type_append(struct type *list, struct type *elem); -/** - * Check if \p node has \p flags set. - * All flags have to be set. - * - * @param node Node to check flags for. - * @param flags Flags to check. - * @return \c 1 if all \p flags are set, \c 0 othewise. - */ -unsigned ast_flags(struct ast_node *node, enum ast_flag flags); +void ast_set_flags(struct ast *node, enum ast_flags flags); +void ast_clear_flags(struct ast *node, enum ast_flags flags); +unsigned ast_flags(struct ast *node, enum ast_flags flags); -/** - * Call external callback on all nodes in tree. - * - * @param call Callback to call. - * @param node Node whose all subnodes should be passed to \p call. - * @param data Extra data to pass to \p call. - * @return Whatever \p call returns. - */ -int ast_call_on(int (*call)(struct ast_node *, void *), - struct ast_node *node, void *data); +typedef int (*ast_callback_t)(struct ast *, void *); +typedef int (*type_callback_t)(struct type *, void *); +int ast_visit(ast_callback_t before, ast_callback_t after, struct ast *node, void *data); +int ast_visit_list(ast_callback_t before, ast_callback_t after, struct ast *node, void *data); -int ast_call_on_chain(int (*call)(struct ast_node *, void *), - struct ast_node *node, void *data); +int type_visit(type_callback_t before, type_callback_t after, struct type *node, void *data); +int type_visit_list(type_callback_t before, type_callback_t after, struct type *node, void *data); /** * Number of elements in AST list. @@ -1306,7 +658,7 @@ int ast_call_on_chain(int (*call)(struct ast_node *, void *), * @param list List whose elements to count. * @return Number of elements in \p list. */ -size_t ast_list_len(struct ast_node *list); +size_t ast_list_len(struct ast *list); /** * Get last nose in ASt list. @@ -1314,7 +666,7 @@ size_t ast_list_len(struct ast_node *list); * @param list List whose last element to get. * @return Last node in \p list. */ -struct ast_node *ast_last_node(struct ast_node *list); +struct ast *ast_last(struct ast *list); /** * Get last element in block. @@ -1322,16 +674,22 @@ struct ast_node *ast_last_node(struct ast_node *list); * @param block Block whose last element to get. * @return Last node in block. */ -struct ast_node *ast_block_last(struct ast_node *block); +struct ast *ast_block_last(struct ast *block); -void destroy_ast_nodes(); -const char *primitive_str(enum ast_primitive type); +void destroy_allocs(); +const char *primitive_str(struct type *kind); -int same_id(struct ast_node *id1, struct ast_node *id2); -int equiv_nodes(struct ast_node *n1, struct ast_node *n2); -int equiv_node_chains(struct ast_node *c1, struct ast_node *c2); +int same_id(char *id1, char *id2); +int equiv_nodes(struct ast *n1, struct ast *n2); +int equiv_node_lists(struct ast *c1, struct ast *c2); + +int equiv_types(struct type *t1, struct type *t2); +int equiv_type_lists(struct type *t1, struct type *t2); #define foreach_node(iter, nodes) \ - for (struct ast_node *iter = nodes; iter; iter = iter->next) + for (struct ast *iter = nodes; iter; iter = iter->n) + +#define foreach_type(iter, nodes) \ + for (struct type *iter = nodes; iter; iter = iter->n) #endif /* AST_H */ diff --git a/include/ek/debug.h b/include/ek/debug.h index 588fc6b..79cc1d1 100644 --- a/include/ek/debug.h +++ b/include/ek/debug.h @@ -65,15 +65,7 @@ struct file_ctx { * @param type Type to generate string representation of. * @return \p type as string. */ -char *type_str(struct ast_node *type); - -/** - * Generate string representation of call. - * - * @param call Call to generate string representation of. - * @return \p call as string. - */ -char *call_str(struct ast_node *call); +char *type_str(struct type *type); /** * Print info that relates to a specific AST node. @@ -84,8 +76,8 @@ char *call_str(struct ast_node *call); * @param node AST node to print message with. * @param fmt Format string. Follows standard printf() formatting. */ -void semantic_info(struct file_ctx ctx, struct ast_node *node, const char *fmt, - ...); +void semantic_info(struct file_ctx ctx, struct ast *node, const char *fmt, ...); +void type_info(struct file_ctx ctx, struct type *node, const char *fmt, ...); /** * Print warning that relates to a specific AST node. @@ -100,7 +92,7 @@ void semantic_info(struct file_ctx ctx, struct ast_node *node, const char *fmt, * @param node AST node to print message with. * @param fmt Format string. Follows standard printf() formatting. */ -void semantic_warn(struct file_ctx ctx, struct ast_node *node, const char *fmt, +void semantic_warn(struct file_ctx ctx, struct ast *node, const char *fmt, ...); /** @@ -111,8 +103,8 @@ void semantic_warn(struct file_ctx ctx, struct ast_node *node, const char *fmt, * @param node AST node to print message with. * @param fmt Format string. Follows standard printf() formatting. */ -void semantic_error(struct file_ctx ctx, struct ast_node *node, const char *fmt, - ...); +void semantic_error(struct file_ctx ctx, struct ast *node, const char *fmt, ...); +void type_error(struct file_ctx ctx, struct type *type, const char *fmt, ...); /** * Print internal error. diff --git a/include/ek/lower.h b/include/ek/lower.h index af203d6..d635178 100644 --- a/include/ek/lower.h +++ b/include/ek/lower.h @@ -4,6 +4,6 @@ #include <ek/ast.h> #include <stdio.h> -int lower_actuals(struct scope *root); +int lower(struct scope *root); #endif /* EK_OPS_H */ diff --git a/include/ek/parser.h b/include/ek/parser.h index c548f7f..49d9302 100644 --- a/include/ek/parser.h +++ b/include/ek/parser.h @@ -30,7 +30,7 @@ struct parser { /** How deeply we've nested comments. */ size_t comment_nesting; /** Raw AST. */ - struct ast_node *tree; + struct ast *tree; }; /** diff --git a/include/ek/scope.h b/include/ek/scope.h index 4cef3a1..4858b55 100644 --- a/include/ek/scope.h +++ b/include/ek/scope.h @@ -34,9 +34,9 @@ enum scope_flags { */ struct visible { /** Name of the visible node. */ - struct ast_node *id; + char *id; /** AST node that is visible. */ - struct ast_node *node; + struct ast *node; /** Next visible object in the scope we're in. */ struct visible *next; }; @@ -44,15 +44,15 @@ struct visible { /** Actualized nodes visible to scope. */ struct actual { /** Actualized AST node. */ - struct ast_node *node; + struct ast *node; /** Next actual node. */ struct actual *next; }; -struct types { - struct ast_node *id; - struct ast_node *type; - struct ast_node *next; +struct type_defs { + char *id; + struct ast *type_def; + struct type_defs *next; }; /** @@ -160,7 +160,7 @@ void scope_destroy_defaults(struct scope *root); * @param scratch Scratch node to add to \p scope. * @return \c 0 when successful, non-zero otherwise. */ -int scope_add_scratch(struct scope *scope, struct ast_node *scratch); +int scope_add_scratch(struct scope *scope, struct ast *scratch); /** * Set scope flags. @@ -178,7 +178,7 @@ void scope_set_flags(struct scope *scope, enum scope_flags flags); * @return \c 1 if flags are set, \c 0 if flags are unset. * @note All flags have to be set for the result to be \c 1. */ -int scope_flags(struct scope *scope, enum scope_flags flags); +unsigned scope_flags(struct scope *scope, enum scope_flags flags); /** * Add child scope to \p parent. @@ -196,7 +196,7 @@ void scope_add_scope(struct scope *parent, struct scope *child); * @param node Actualized AST node. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_actual(struct scope *scope, struct ast_node *node); +int scope_add_actual(struct scope *scope, struct ast *node); /** * Add variable to scope. @@ -206,7 +206,7 @@ int scope_add_actual(struct scope *scope, struct ast_node *node); * @param var Variable to add to scope. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_var(struct scope *scope, struct ast_node *var); +int scope_add_var(struct scope *scope, struct ast *var); /** * Add type to scope. @@ -216,8 +216,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 *id, - struct ast_node *type); +int scope_add_type(struct scope *scope, char *id, struct ast *type); /** * Add procedure to scope. @@ -227,7 +226,7 @@ int scope_add_type(struct scope *scope, struct ast_node *id, * @param proc Procedure to add to scope. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_proc(struct scope *scope, struct ast_node *proc); +int scope_add_proc(struct scope *scope, struct ast *proc); /** * Add macro to scope. @@ -237,7 +236,7 @@ int scope_add_proc(struct scope *scope, struct ast_node *proc); * @param macro Macro to add to scope. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_macro(struct scope *scope, struct ast_node *macro); +int scope_add_macro(struct scope *scope, struct ast *macro); /** * Add template to scope. @@ -247,7 +246,7 @@ int scope_add_macro(struct scope *scope, struct ast_node *macro); * @param type_template Template to add to scope. * @return \c 0 when succesful, non-zero otherwise. */ -int scope_add_trait(struct scope *scope, struct ast_node *trait); +int scope_add_trait(struct scope *scope, struct ast *trait); int scope_resolve(struct scope *scope); @@ -261,7 +260,7 @@ int scope_resolve(struct scope *scope); * @return Pointer to the AST node corresponding to \p id if found, * otherwise \c NULL. */ -struct ast_node *scope_find_var(struct scope *scope, struct ast_node *id); +struct ast *scope_find_var(struct scope *scope, char *id); /** * Find a type with ID in \p scope. @@ -273,7 +272,7 @@ struct ast_node *scope_find_var(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_type(struct scope *scope, struct ast_node *id); +struct ast *scope_find_type(struct scope *scope, char *id); /** * Find a procedure with ID in \p scope. @@ -285,7 +284,7 @@ struct ast_node *scope_find_type(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_proc(struct scope *scope, struct ast_node *id); +struct ast *scope_find_proc(struct scope *scope, char *id); /** * Find a macro with ID in \p scope. @@ -297,7 +296,7 @@ struct ast_node *scope_find_proc(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_macro(struct scope *scope, struct ast_node *id); +struct ast *scope_find_macro(struct scope *scope, char *id); /** * Find an alias with ID in \p scope. @@ -309,7 +308,7 @@ struct ast_node *scope_find_macro(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_alias(struct scope *scope, struct ast_node *id); +struct ast *scope_find_alias(struct scope *scope, char *id); /** * Find a template with ID in \p scope. @@ -321,7 +320,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_trait(struct scope *scope, struct ast_node *id); +struct ast *scope_find_trait(struct scope *scope, char *id); /** * Find a variable with ID visible to \p scope. @@ -331,7 +330,7 @@ struct ast_node *scope_find_trait(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 *file_scope_find_var(struct scope *scope, struct ast_node *id); +struct ast *file_scope_find_var(struct scope *scope, char *id); /** * Find a type with ID visible to \p scope. @@ -341,7 +340,7 @@ struct ast_node *file_scope_find_var(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 *file_scope_find_type(struct scope *scope, struct ast_node *id); +struct ast *file_scope_find_type(struct scope *scope, char *id); /** * Find a procedure with ID visible to \p scope. @@ -351,7 +350,7 @@ struct ast_node *file_scope_find_type(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 *file_scope_find_proc(struct scope *scope, struct ast_node *id); +struct ast *file_scope_find_proc(struct scope *scope, char *id); /** * Find a macro with ID visible to \p scope. @@ -361,8 +360,7 @@ struct ast_node *file_scope_find_proc(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 *file_scope_find_macro(struct scope *scope, - struct ast_node *id); +struct ast *file_scope_find_macro(struct scope *scope, char *id); /** * Find a alias with ID visible to \p scope. * @@ -371,8 +369,7 @@ struct ast_node *file_scope_find_macro(struct scope *scope, * @return Pointer to the AST node corresponding to \p id if found, * otherwise \c NULL. */ -struct ast_node *file_scope_find_alias(struct scope *scope, - struct ast_node *id); +struct ast *file_scope_find_alias(struct scope *scope, char *id); /** * Find a template with ID visible to \p scope. @@ -382,7 +379,9 @@ 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_trait(struct scope *scope, - struct ast_node *id); +struct ast *file_scope_find_trait(struct scope *scope, char *id); + +#define foreach_visible(iter, init)\ + for (struct visible *iter = init; iter; iter = iter->next) #endif /* SCOPE_H */ diff --git a/include/ek/vec.h b/include/ek/vec.h index 8d5cae1..d9048fe 100644 --- a/include/ek/vec.h +++ b/include/ek/vec.h @@ -35,4 +35,7 @@ void vec_append(struct vec *v, void *n); #define vect_pop(type, v) \ *(type *)vec_pop(&v) +#define vec_uninit(v) \ + (v.buf == NULL) + #endif /* VEC_H */ |
