#ifndef HARE_AST_H #define HARE_AST_H #include #include #include "expr.h" #include "identifier.h" #include "lex.h" #include "types.h" struct ast_type; enum ast_import_mode { IMPORT_NORMAL, // use foo::bar; IMPORT_ALIAS, // use foo = bar::baz; IMPORT_MEMBERS, // use foo::{bar, baz}; IMPORT_WILDCARD, // use foo::bar::*; }; struct ast_import_members { struct location loc; struct ident *name; struct ast_import_members *next; }; struct ast_imports { enum ast_import_mode mode; struct ident *ident; union { const char *alias; struct ast_import_members *members; }; struct ast_imports *next; }; struct ast_array_type { struct ast_expression *length; // NULL for unbounded arrays struct ast_type *members; bool contextual; }; struct ast_slice_type { struct ast_type *members; }; struct ast_enum_field { struct location loc; struct ident *name; struct ast_expression *value; struct ast_enum_field *next; }; struct ast_enum_type { enum type_storage storage; struct ast_enum_field *values; }; struct ast_function_parameters { struct location loc; struct ident *name; struct ast_type *type; struct ast_expression *default_value; struct ast_function_parameters *next; }; struct ast_function_type { struct ast_type *result; struct ast_function_parameters *params; enum variadism variadism; }; struct ast_pointer_type { struct ast_type *referent; bool nullable; }; struct ast_tagged_union_type { struct ast_type *type; bool unwrap; struct ast_tagged_union_type *next; }; struct ast_tuple_type { struct ast_type *type; struct ast_tuple_type *next; }; struct ast_struct_union_field { struct ast_struct_union_field *next; const char *name; // null if embed, may be "_" struct ast_type *type; }; struct ast_struct_union_type { struct ast_struct_union_field fields; bool packed; }; struct ast_type { struct location loc; enum type_storage storage; union { struct ast_array_type array; struct ast_type *error; struct ast_function_type func; struct ast_pointer_type pointer; struct ast_slice_type slice; struct ast_struct_union_type struct_union; struct ast_tagged_union_type tagged; struct ast_tuple_type tuple; struct { struct ident *alias; // Only valid for enums struct ast_enum_type _enum; }; }; }; struct ast_types { const struct ast_type *type; struct ast_types *next; }; struct ast_expression_list { struct ast_expression *expr; struct ast_expression_list *next; }; struct ast_expression_access { enum access_type type; union { struct ident *ident; struct { struct ast_expression *array; struct ast_expression *index; }; struct { struct ast_expression *_struct; const char *field; }; struct { struct ast_expression *tuple; struct ast_expression *value; }; }; }; struct ast_expression_alloc { enum alloc_kind kind; struct ast_expression *init; struct ast_expression *cap; }; struct ast_expression_append { struct ast_expression *object; struct ast_expression *value; struct ast_expression *length; bool is_static, is_multi; }; struct ast_expression_assert { struct ast_expression *cond; struct ast_expression *message; bool is_static; }; struct ast_expression_assign { enum binarithm_operator op; // object == NULL for discarding assignment (`_ = foo`) struct ast_expression *object, *value; }; struct ast_expression_binarithm { enum binarithm_operator op; struct ast_expression *lvalue, *rvalue; }; struct ast_binding_names { struct ident *name; // NULL for _ struct ast_binding_names *next; }; struct ast_expression_binding { // more than one name means tuple unpacking, // otherwise it's a regular binding struct ast_binding_names names; struct ast_type *type; bool is_static; struct ast_expression *initializer; struct ast_expression_binding *next; }; struct ast_expression_call { struct ast_expression *lvalue; struct ast_expression_list *args; bool variadic; // last argument is a variadic argument list }; struct ast_expression_cast { enum cast_kind kind; struct ast_expression *value; struct ast_type *type; }; struct ast_expression_literal { enum type_storage storage; union { int64_t ival; uint64_t uval; double fval; uint32_t rune; bool bval; struct { size_t len; char *value; } string; struct { struct ast_expression_list *exprs; bool expand; } array; }; }; struct ast_expression_control { const char *label; // Never set for return. struct ast_expression *value; // Never set for continue }; struct ast_expression_defer { struct ast_expression *deferred; }; struct ast_expression_delete { struct ast_expression *expr; bool is_static; }; struct ast_expression_for { enum for_kind kind; const char *label; struct ast_expression *bindings; struct ast_expression *cond; struct ast_expression *afterthought; struct ast_expression *body; struct ast_expression *else_branch; }; struct ast_expression_free { struct ast_expression *expr; }; struct ast_expression_if { struct ast_expression *cond; struct ast_expression *true_branch, *false_branch; }; struct ast_expression_compound { const char *label; struct location label_loc; struct ast_expression_list list; }; struct ast_match_case { struct ident *name; // May be null struct ast_type *type; struct ast_expression_list exprs; struct ast_match_case *next; }; struct ast_expression_match { const char *label; struct ast_expression *value; struct ast_match_case *cases; }; enum measure_operator { M_ALIGN, M_LEN, M_SIZE, M_OFFSET, }; struct ast_expression_measure { enum measure_operator op; union { struct ast_expression *value; struct ast_type *type; // TODO: Field selection }; }; struct ast_expression_propagate { struct ast_expression *value; bool abort; }; struct ast_expression_slice { struct ast_expression *object; struct ast_expression *start, *end; }; struct ast_case_option { struct ast_expression *value; struct ast_case_option *next; }; struct ast_switch_case { struct ast_case_option *options; // NULL for * struct ast_expression_list exprs; struct ast_switch_case *next; }; struct ast_expression_switch { const char *label; struct ast_expression *value; struct ast_switch_case *cases; }; struct ast_field_value { const char *name; struct ast_type *type; struct ast_expression *initializer; struct ast_field_value *next; }; struct ast_expression_struct { bool autofill; bool undefined; struct ident *type; struct ast_field_value *fields; }; struct ast_expression_tuple { struct ast_expression *expr; struct ast_expression_tuple *next; }; struct ast_expression_unarithm { enum unarithm_operator op; struct ast_expression *operand; }; struct ast_expression_vaarg { struct ast_expression *ap; struct ast_type *type; }; struct ast_expression { struct location loc; enum expr_type type; union { struct ast_expression_access access; struct ast_expression_alloc alloc; struct ast_expression_append append; // also insert struct ast_expression_assert assert; struct ast_expression_assign assign; struct ast_expression_binarithm binarithm; struct ast_expression_binding binding; struct ast_expression_call call; struct ast_expression_cast cast; struct ast_expression_compound compound; struct ast_expression_control control; struct ast_expression_defer defer; struct ast_expression_delete delete; struct ast_expression_for _for; struct ast_expression_free free; struct ast_expression_if _if; struct ast_expression_literal literal; struct ast_expression_match match; struct ast_expression_measure measure; struct ast_expression_propagate propagate; struct ast_expression_slice slice; struct ast_expression_struct _struct; struct ast_expression_switch _switch; struct ast_expression_tuple tuple; struct ast_expression_unarithm unarithm; struct ast_expression_vaarg vaarg; }; }; struct ast_global_decl { const char *symbol; bool threadlocal; struct ident *ident; struct ast_type *type; struct ast_expression *init; }; struct ast_type_decl { struct ident *ident; struct ast_type *type; }; enum func_decl_flags { FN_FINI = 1 << 0, FN_INIT = 1 << 1, FN_TEST = 1 << 2, }; struct ast_function_decl { const char *symbol; struct ident *ident; struct ast_function_type prototype; struct ast_expression *body; enum func_decl_flags flags; }; enum ast_decl_type { ADECL_FUNC, ADECL_TYPE, ADECL_GLOBAL, ADECL_CONST, ADECL_ASSERT, }; struct ast_decl { struct location loc; enum ast_decl_type decl_type; bool exported; union { struct ast_global_decl global; struct ast_global_decl constant; struct ast_type_decl type; struct ast_function_decl function; struct ast_expression_assert assert; }; }; struct ast_decls { struct ast_decl decl; struct ast_decls *next; }; struct ast_subunit { struct ast_imports *imports; struct ast_decls *decls; struct ast_subunit *next; }; struct ast_unit { struct ident *ns; struct ast_subunit subunits; }; #endif