diff --git a/src/compiler/ast.c b/src/compiler/ast.c index b688eb5c8..fa148aab8 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -4,25 +4,6 @@ #include "compiler_internal.h" -static void fprint_asts_recursive(Context *context, FILE *file, Ast **asts, int indent); -static void fprint_decl_list(Context *context, FILE *file, Decl **decls, int indent); -static void fprint_ast_recursive(Context *context, FILE *file, Ast *ast, int indent); -static void fprint_expr_list(Context *context, FILE *file, Expr **exprs, int indent); - -#define DUMP(text) do { fprintf_indented(file, indent, text); fprintf(file, "\n"); } while(0) -#define DUMPF(text, ...) do { fprintf_indented(file, indent, text, __VA_ARGS__); fprintf(file, "\n"); } while(0) -#define DUMPI(text) do { fprintf_indented(file, indent + 1, text); fprintf(file, "\n"); } while(0) -#define DUMPFI(text, ...) do { fprintf_indented(file, indent + 1, text, __VA_ARGS__); fprintf(file, "\n"); } while(0) -#define DUMPE() fprint_endparen(file, indent) -#define DUMPEND() fprint_endparen(file, indent); return -#define DUMPEXPR(_expr) fprint_expr_recursive(context, file, _expr, indent + 1) -#define DUMPAST(_ast) fprint_ast_recursive(context, file, _ast, indent + 1) -#define DUMPASTS(_asts) fprint_asts_recursive(context, file, _asts, indent + 1) -#define DUMPTI(_type_info) fprint_type_info_recursive(context, file, _type_info, indent + 1) -#define DUMPTYPE(_type) fprint_type_recursive(context, file, _type, indent + 1) -#define DUMPDECLS(_decls) fprint_decl_list(context, file, _decls, indent + 1) -#define DUMPDECL(_decl) fprint_decl_recursive(context, file, _decl, indent + 1) -#define DUMPEXPRS(_exprs) fprint_expr_list(context, file, _exprs, indent + 1) Decl *decl_new(DeclKind decl_kind, TokenId name, Visibility visibility) { @@ -210,41 +191,6 @@ Decl *decl_new_with_type(TokenId name, DeclKind decl_type, Visibility visibility return decl; } -const char *decl_var_to_string(VarDeclKind kind) -{ - switch (kind) - { - case VARDECL_CONST: - return "const"; - case VARDECL_GLOBAL: - return "global"; - case VARDECL_LOCAL: - return "local"; - case VARDECL_MEMBER: - return "member"; - case VARDECL_PARAM: - return "param"; - case VARDECL_UNWRAPPED: - return "alias"; - case VARDECL_PARAM_CT: - return "$param"; - case VARDECL_PARAM_CT_TYPE: - return "$Param"; - case VARDECL_PARAM_EXPR: - return "#param"; - case VARDECL_PARAM_REF: - return "¶m"; - case VARDECL_LOCAL_CT: - return "$local"; - case VARDECL_LOCAL_CT_TYPE: - return "$Local"; - case VARDECL_REWRAPPED: - case VARDECL_ERASE: - UNREACHABLE - } - UNREACHABLE -} - static Decl poison_decl = { .decl_kind = DECL_POISONED, .resolve_status = RESOLVE_DONE }; Decl *poisoned_decl = &poison_decl; @@ -373,986 +319,12 @@ UnaryOp unaryop_from_token(TokenType type) return unary_op[type]; } -TokenType unaryop_to_token(UnaryOp type) -{ - for (unsigned i = 0; i <= TOKEN_LAST; i++) - { - if (unary_op[i] == type) return (TokenType)i; - } - return TOKEN_INVALID_TOKEN; -} - PostUnaryOp post_unaryop_from_token(TokenType type) { return post_unary_op[type]; } -TokenType postunaryop_to_token(PostUnaryOp type) -{ - for (unsigned i = 0; i <= TOKEN_LAST; i++) - { - if (post_unary_op[i] == type) return (TokenType)i; - } - return TOKEN_INVALID_TOKEN; -} - static Ast poison_ast = { .ast_kind = AST_POISONED }; Ast *poisoned_ast = &poison_ast; -void fprint_indent(FILE *file, int indent) -{ - for (int i = 0; i < indent * 2; i++) fprintf(file, " "); -} - -static void fprintf_indented(FILE *file, int indent, const char *string, ...) -{ - fprint_indent(file, indent); - va_list list; - va_start(list, string); - vfprintf(file, string, list); - va_end(list); -} - -void fprint_endparen(FILE *file, int indent) -{ - fprint_indent(file, indent); - fprintf(file, ")\n"); -} - -void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent); - -void fprint_type_recursive(Context *context, FILE *file, Type *type, int indent) -{ - if (!type) - { - DUMP("(none)"); - return; - } - switch (type->type_kind) - { - case TYPE_BITSTRUCT: - DUMP("(bitstruct"); - return; - case TYPE_ERRTYPE: - DUMPF("(errtype %s)", type->name); - return; - case TYPE_DISTINCT: - DUMPF("(distinct %s)", type->name); - return; - case TYPE_VECTOR: - DUMP("(type vector"); - return; - case TYPE_TYPEINFO: - DUMP("(type typeinfo)"); - return; - case TYPE_POISONED: - DUMP("(type poison)"); - return; - case TYPE_TYPEID: - DUMP("(typeid)"); - return; - case TYPE_FUNC: - DUMPF("(func-type %s)", type->name); - return; - case TYPE_STRUCT: - DUMPF("(struct %s)", type->name); - return; - case TYPE_UNION: - DUMPF("(union %s)", type->name); - return; - case TYPE_ENUM: - DUMPF("(enum %s)", type->name); - return; - case TYPE_TYPEDEF: - DUMPF("(typedef %s", type->name); - DUMPTYPE(type->canonical); - DUMPEND(); - case TYPE_POINTER: - DUMP("(pointer"); - DUMPTYPE(type->pointer); - DUMPEND(); - case TYPE_SUBARRAY: - DUMP("(subarray"); - DUMPTYPE(type->array.base); - DUMPEND(); - case TYPE_INFERRED_ARRAY: - DUMP("(inferred-array"); - DUMPTYPE(type->array.base); - DUMPEND(); - case TYPE_ARRAY: - DUMPF("(array [%zu]", type->array.len); - DUMPTYPE(type->array.base); - DUMPEND(); - case TYPE_VOID: - case TYPE_BOOL: - case ALL_SIGNED_INTS: - case ALL_UNSIGNED_INTS: - case ALL_REAL_FLOATS: - DUMPF("(%s)", type->name); - return; - case TYPE_VIRTUAL_ANY: - DUMP("(virtual*)"); - return; - case TYPE_VIRTUAL: - DUMPF("(virtual %s*)", type->name); - return; - case TYPE_IXX: - DUMP("(ct int)"); - return; - case TYPE_FXX: - DUMP("(ct float)"); - return; - case TYPE_STRLIT: - DUMP("(ct string)"); - return; - case TYPE_ANYERR: - DUMP("(any-error)"); - return; - } -} - -const char *resolve_status_to_string(ResolveStatus status) -{ - switch (status) - { - case RESOLVE_NOT_DONE: - return "not_done"; - case RESOLVE_DONE: - return "done"; - case RESOLVE_RUNNING: - return "running"; - default: - UNREACHABLE - } -} - - -void fprint_type_info_recursive(Context *context, FILE *file, TypeInfo *type_info, int indent) -{ - if (!type_info) - { - DUMP("(type_info missing)"); - return; - } - DUMP("(type_info"); - DUMPFI("(resolve_status %s)", resolve_status_to_string(type_info->resolve_status)); - if (type_info->resolve_status == RESOLVE_DONE) - { - DUMPTYPE(type_info->type); - DUMPEND(); - } - indent++; - switch (type_info->kind) - { - case TYPE_INFO_POISON: - DUMP("(POISON)"); - break; - case TYPE_INFO_IDENTIFIER: - if (type_info->unresolved.path) - { - DUMPF("(unresolved %s::%s)\n", type_info->unresolved.path->module, TOKSTR(type_info->unresolved.name_loc)); - break; - } - DUMPF("(unresolved %s)", TOKSTR(type_info->unresolved.name_loc)); - break; - case TYPE_INFO_SUBARRAY: - DUMP("(subarray"); - DUMPTI(type_info->array.base); - DUMPE(); - break; - case TYPE_INFO_ARRAY: - DUMP("(unresolved-array"); - DUMPTI(type_info->array.base); - DUMPEXPR(type_info->array.len); - DUMPE(); - break; - case TYPE_INFO_POINTER: - DUMP("(pointer"); - DUMPTI(type_info->pointer); - DUMPE(); - break; - case TYPE_INFO_INC_ARRAY: - DUMP("(incarray"); - DUMPTI(type_info->array.base); - DUMPE(); - break; - case TYPE_INFO_INFERRED_ARRAY: - DUMP("(inferredarray"); - DUMPTI(type_info->array.base); - DUMPE(); - break; - case TYPE_INFO_EXPRESSION: - DUMP("(typexpr"); - DUMPEXPR(type_info->unresolved_type_expr); - DUMPE(); - break; - } - indent--; - DUMPEND(); -} - -void fprint_expr_common(Context *context, FILE *file, Expr *expr, int indent) -{ - switch (expr->resolve_status) - { - case RESOLVE_NOT_DONE: - DUMP("(unresolved)"); - return; - case RESOLVE_RUNNING: - DUMP("(resolving)"); - return; - case RESOLVE_DONE: - DUMPTYPE(expr->type); - return; - } - UNREACHABLE -} - -#define DUMPEXPC(_expr) fprint_expr_common(context, file, _expr, indent + 1) - -void fprint_expr_recursive(Context *context, FILE *file, Expr *expr, int indent) -{ - if (!expr) return; - switch (expr->expr_kind) - { - case EXPR_BYTES: - DUMP("(bytes"); - break; - case EXPR_DECL: - DUMP("(decl"); - DUMPEXPC(expr); - DUMPDECL(expr->decl_expr); - break; - case EXPR_TRY_UNWRAP_CHAIN: - DUMP("(try-unwrap-chain"); - DUMPEXPC(expr); - DUMPEXPRS(expr->try_unwrap_chain_expr); - break; - case EXPR_CATCH_UNWRAP: - DUMP("(catch-unwrap"); - DUMPEXPC(expr); - DUMPEXPRS(expr->catch_unwrap_expr.exprs); - break; - case EXPR_TRY_UNWRAP: - DUMP("(try-unwrap"); - DUMPEXPC(expr); - DUMPEXPR(expr->try_unwrap_expr.init); - break; - case EXPR_NOP: - DUMP("(nop)"); - return; - case EXPR_FLATPATH: - DUMP("(idents)"); - return; - case EXPR_CT_CALL: - DUMP("(ct-call)"); - return; - case EXPR_MACRO_BODY_EXPANSION: - DUMP("(macro-body-expansion)"); - return; - case EXPR_PLACEHOLDER: - DUMP("(placeholder)"); - return; - case EXPR_DESIGNATOR: - DUMP("(named param)"); - return; - case EXPR_UNDEF: - DUMP("(undef)"); - return; - case EXPR_TYPEINFO: - DUMP("(typeinfo)"); - return; - case EXPR_SLICE_ASSIGN: - DUMP("(sliceassign"); - DUMPEXPC(expr); - DUMPEXPR(expr->slice_assign_expr.left); - DUMPEXPR(expr->slice_assign_expr.right); - DUMPEND(); - case EXPR_LEN: - DUMP("(len"); - DUMPEXPC(expr); - DUMPEXPR(expr->len_expr.inner); - DUMPEND(); - case EXPR_COND: - DUMP("(decllist"); - DUMPEXPRS(expr->cond_expr); - DUMPEND(); - case EXPR_FAILABLE: - DUMP("(failable"); - DUMPEXPC(expr); - DUMPEXPR(expr->failable_expr); - DUMPEND(); - case EXPR_MACRO_EXPANSION: - DUMP("(macro expansion"); - DUMPEXPR(expr->macro_expansion_expr.inner); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_IDENTIFIER: - DUMPF("(ident %s", TOKSTR(expr->identifier_expr.identifier)); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_CT_IDENT: - DUMPF("(ctident %s", TOKSTR(expr->ct_ident_expr.identifier)); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_HASH_IDENT: - DUMPF("(hashident %s", TOKSTR(expr->hash_ident_expr.identifier)); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_CONST_IDENTIFIER: - DUMPF("(ident %s", TOKSTR(expr->identifier_expr.identifier)); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_MACRO_BLOCK: - DUMP("(macro_block"); - DUMPASTS(expr->macro_block.stmts); - DUMPDECLS(expr->macro_block.params); - DUMPEND(); - case EXPR_EXPR_BLOCK: - if (!expr->expr_block.stmts) - { - DUMP("(expr_block)"); - return; - } - DUMP("(expr_block"); - DUMPASTS(expr->expr_block.stmts); - DUMPEND(); - case EXPR_CONST: - fprintf_indented(file, indent, "(const "); - expr_const_fprint(file, &expr->const_expr); - fprintf(file, "\n"); - DUMPEXPC(expr); - DUMPEND(); - case EXPR_BINARY: - DUMPF("(binary %s", token_type_to_string(binaryop_to_token(expr->binary_expr.operator))); - DUMPEXPC(expr); - DUMPEXPR(expr->binary_expr.left); - DUMPEXPR(expr->binary_expr.right); - DUMPEND(); - case EXPR_UNARY: - DUMPF("(unary %s", token_type_to_string(unaryop_to_token(expr->unary_expr.operator))); - DUMPEXPC(expr); - DUMPEXPR(expr->unary_expr.expr); - DUMPEND(); - case EXPR_POST_UNARY: - DUMPF("(postunary %s", token_type_to_string(postunaryop_to_token(expr->post_expr.operator))); - DUMPEXPC(expr); - DUMPEXPR(expr->post_expr.expr); - DUMPEND(); - case EXPR_TRY: - DUMPF("(try %d", expr->try_expr.is_try); - DUMPEXPC(expr); - DUMPEXPR(expr->try_expr.expr); - DUMPEND(); - case EXPR_TRY_ASSIGN: - DUMPF("(try-assign %d", expr->try_assign_expr.is_try); - DUMPEXPC(expr); - DUMPEXPR(expr->try_assign_expr.expr); - DUMPEXPR(expr->try_assign_expr.init); - DUMPEND(); - case EXPR_ACCESS: - DUMP("(access"); - DUMPEXPC(expr); - DUMPEXPR(expr->access_expr.parent); - DUMPEXPR(expr->access_expr.child); - DUMPEND(); - case EXPR_TYPEID: - DUMP("(typeid"); - DUMPEXPC(expr); - DUMPTI(expr->typeid_expr); - DUMPEND(); - case EXPR_GROUP: - DUMP("(group"); - DUMPEXPR(expr->group_expr); - DUMPEND(); - case EXPR_CALL: - DUMP("(call"); - DUMPEXPC(expr); - DUMPEXPR(expr->call_expr.function); - indent++; - DUMP("(args"); - VECEACH(expr->call_expr.arguments, i) - { - DUMPEXPR(expr->call_expr.arguments[i]); - } - DUMPE(); - indent--; - DUMPEND(); - case EXPR_TERNARY: - if (!expr->ternary_expr.then_expr) - { - DUMP("(elvis"); - DUMPEXPC(expr); - DUMPEXPR(expr->ternary_expr.cond); - } - else - { - DUMP("(cond"); - DUMPEXPC(expr); - DUMPEXPR(expr->ternary_expr.cond); - DUMPEXPR(expr->ternary_expr.then_expr); - } - DUMPEXPR(expr->ternary_expr.else_expr); - DUMPEND(); - case EXPR_INITIALIZER_LIST: - fprintf_indented(file, indent, "(initializerlist "); - switch (expr->initializer_expr.init_type) - { - case INITIALIZER_UNKNOWN: - fprintf(file, "not-analyzed\n"); - break; - case INITIALIZER_CONST: - fprintf(file, "const\n"); - break; - case INITIALIZER_NORMAL: - fprintf(file, "normal\n"); - break; - case INITIALIZER_DESIGNATED: - fprintf(file, "designated\n"); - break; - } - DUMPEXPC(expr); - VECEACH(expr->initializer_expr.initializer_expr, i) - { - DUMPEXPR(expr->initializer_expr.initializer_expr[i]); - } - DUMPEND(); - case EXPR_SUBSCRIPT: - DUMP("(subscript"); - DUMPEXPC(expr); - DUMPEXPR(expr->subscript_expr.expr); - DUMPEXPC(expr->subscript_expr.index); - DUMPEND(); - case EXPR_SLICE: - DUMP("(slice"); - DUMPEXPC(expr); - DUMPEXPR(expr->slice_expr.expr); - DUMPEXPR(expr->slice_expr.start); - DUMPEXPR(expr->slice_expr.end); - DUMPEND(); - case EXPR_GUARD: - DUMP("(guard"); - DUMPEXPR(expr->guard_expr.inner); - DUMPEND(); - case EXPR_ELSE: - if (expr->else_expr.is_jump) - { - DUMP("(else-jump"); - DUMPEXPC(expr); - DUMPEXPR(expr->else_expr.expr); - DUMPAST(expr->else_expr.else_stmt); - DUMPEND(); - } - else - { - DUMP("(else-expr"); - DUMPEXPC(expr); - DUMPEXPR(expr->else_expr.expr); - DUMPEXPR(expr->else_expr.else_expr); - DUMPEND(); - } - UNREACHABLE - case EXPR_CAST: - DUMP("(cast\n"); - DUMPEXPC(expr); - DUMPTI(expr->cast_expr.type_info); - DUMPEXPR(expr->cast_expr.expr); - DUMPEND(); - case EXPR_EXPRESSION_LIST: - DUMP("(expression-list"); - DUMPEXPC(expr); - DUMPTI(expr->struct_value_expr.type); - VECEACH(expr->expression_list, i) - { - fprint_expr_recursive(context, file, expr->expression_list[i], indent + 1); - } - DUMPEND(); - case EXPR_POISONED: - DUMP("(POISONED)"); - return; - case EXPR_TYPEOF: - DUMP("(typeof"); - DUMPEXPR(expr->typeof_expr); - DUMPEND(); - case EXPR_SCOPED_EXPR: - DUMP("(scopedexpr"); - DUMPEXPR(expr->expr_scope.expr); - // TODO defers. - DUMPEND(); - case EXPR_COMPOUND_LITERAL: - DUMP("(compound-literal"); - DUMPTI(expr->expr_compound_literal.type_info); - DUMPEXPR(expr->expr_compound_literal.initializer); - DUMPEND(); - } - UNREACHABLE -} - - -void fprint_func_signature(Context *context, FILE *file, FunctionSignature *signature, int indent) -{ - DUMP("(func-sig"); - DUMPTI(signature->rtype); - do - { - if (!vec_size(signature->params)) - { - DUMPI("(params none)"); - break; - } - indent++; - DUMP("(params"); - DUMPDECLS(signature->params); - DUMPE(); - indent--; - } while (false); - DUMPEND(); -} - -void fprint_decl_recursive(Context *context, FILE *file, Decl *decl, int indent) -{ - if (!decl) return; - switch (decl->decl_kind) - { - case DECL_BITSTRUCT: - DUMP("(bitstruct)"); - return; - case DECL_INTERFACE: - DUMPF("(interface %s", decl->name); - DUMPDECLS(decl->interface_decl.members); - DUMPDECLS(decl->interface_decl.functions); - DUMPEND(); - case DECL_VAR: - DUMPF("(var-%s %s", decl_var_to_string(decl->var.kind), decl->name ? decl->name : "anon"); - DUMPTI(decl->var.type_info); - switch (decl->var.kind) - { - case VARDECL_CONST: - case VARDECL_GLOBAL: - case VARDECL_LOCAL: - case VARDECL_PARAM: - case VARDECL_PARAM_CT: - case VARDECL_PARAM_EXPR: - case VARDECL_PARAM_REF: - case VARDECL_MEMBER: - case VARDECL_LOCAL_CT: - DUMPEXPR(decl->var.init_expr); - break; - case VARDECL_PARAM_CT_TYPE: - case VARDECL_LOCAL_CT_TYPE: - DUMPTI(decl->var.type_info); - break; - case VARDECL_UNWRAPPED: - DUMPDECL(decl->var.alias); - break; - case VARDECL_ERASE: - case VARDECL_REWRAPPED: - UNREACHABLE - } - DUMPEND(); - case DECL_CT_ASSERT: - DUMP("$assert"); - DUMPEND(); - case DECL_DEFINE: - DUMPF("(define %s", decl->name); - DUMPEND(); - case DECL_LABEL: - DUMPF("(label %s", decl->name); - DUMPEND(); - case DECL_MACRO: - DUMPF("(macro %s", decl->name); - DUMPTI(decl->macro_decl.rtype); - indent++; - DUMP("(params"); - DUMPDECLS(decl->macro_decl.parameters); - DUMPE(); - indent--; - DUMPAST(decl->macro_decl.body); - DUMPEND(); - case DECL_GENERIC: - DUMPF("(generic %s", decl->name); - DUMPTI(decl->macro_decl.rtype); - indent++; - DUMP("(params"); - DUMPDECLS(decl->macro_decl.parameters); - DUMPE(); - indent--; - DUMPAST(decl->macro_decl.body); - DUMPEND(); - case DECL_FUNC: - DUMPF("(func %s", decl->name); - if (decl->func_decl.type_parent) - { - indent++; - DUMP("(parent_type"); - DUMPTI(decl->func_decl.type_parent); - DUMPE(); - indent--; - } - fprint_func_signature(context, file, &decl->func_decl.function_signature, indent + 1); - if (decl->func_decl.body) DUMPAST(decl->func_decl.body); - DUMPEND(); - case DECL_STRUCT: - DUMPF("(struct %s", decl->name ? decl->name : "anon"); - DUMPDECLS(decl->strukt.members); - DUMPEND(); - case DECL_UNION: - DUMPF("(union %s", decl->name ? decl->name : "anon"); - DUMPDECLS(decl->strukt.members); - DUMPEND(); - case DECL_ENUM: - DUMPF("(enum %s", decl->name); - DUMPTI(decl->enums.type_info); - DUMPDECLS(decl->enums.values); - DUMPEND(); - case DECL_ERRTYPE: - DUMPF("(errtype %s", decl->name); - DUMPTI(decl->enums.type_info); - DUMPDECLS(decl->enums.values); - DUMPEND(); - case DECL_ENUM_CONSTANT: - if (!decl->enum_constant.expr) - { - DUMPF("(enum-constant %s)", decl->name); - return; - } - DUMPF("(enum-constant %s", decl->name); - DUMPEXPR(decl->enum_constant.expr); - DUMPEND(); - case DECL_ERRVALUE: - DUMPF("(errvalue %s)", decl->name); - if (!decl->enum_constant.expr) - { - return; - } - DUMPF("(enum-constant %s", decl->name); - DUMPEXPR(decl->enum_constant.expr); - DUMPEND(); - case DECL_TYPEDEF: - DUMPF("(typedef %s", decl->name); - if (decl->typedef_decl.is_func) - { - fprint_func_signature(context, file, &decl->typedef_decl.function_signature, indent + 1); - } - else - { - DUMPTI(decl->typedef_decl.type_info); - } - DUMPEND(); - case DECL_DISTINCT: - DUMPF("(distinct %s", decl->name); - if (decl->typedef_decl.is_func) - { - fprint_func_signature(context, file, &decl->typedef_decl.function_signature, indent + 1); - } - else - { - DUMPTI(decl->typedef_decl.type_info); - } - DUMPEND(); - case DECL_CT_IF: - DUMP("(ct-if"); - DUMPEXPR(decl->ct_if_decl.expr); - DUMPDECLS(decl->ct_if_decl.then); - if (decl->ct_if_decl.elif) - { - DUMPDECL(decl->ct_if_decl.elif); - } - DUMPEND(); - case DECL_CT_ELIF: - DUMP("(ct-elif"); - DUMPEXPR(decl->ct_elif_decl.expr); - DUMPDECLS(decl->ct_elif_decl.then); - DUMPDECL(decl->ct_elif_decl.elif); - DUMPEND(); - case DECL_CT_ELSE: - DUMP("(ct-else"); - DUMPDECLS(decl->ct_else_decl); - DUMPEND(); - case DECL_POISONED: - DUMP("(poisoned-decl)"); - return; - case DECL_ARRAY_VALUE: - DUMP("(array value"); - DUMPEXPR(decl->incr_array_decl); - DUMPEND(); - case DECL_IMPORT: - DUMPF("(import %s", decl->name); - // TODO - DUMPEND(); - case DECL_CT_CASE: - if (decl->ct_case_decl.type) - { - DUMP("($case"); - DUMPTI(decl->ct_case_decl.type); - } - else - { - DUMP("($default"); - } - DUMPDECLS(decl->ct_case_decl.body); - DUMPEND(); - case DECL_CT_SWITCH: - DUMP("($switch"); - DUMPEXPR(decl->ct_switch_decl.expr); - DUMPDECLS(decl->ct_switch_decl.cases); - DUMPEND(); - case DECL_ATTRIBUTE: - DUMPF("(attribute %s)", decl->name); - if (decl->attr.domains & ATTR_FUNC) - { - DUMPI("(func)"); - } - if (decl->attr.domains & ATTR_GLOBAL) - { - DUMPI("(global)"); - } - if (decl->attr.domains & ATTR_LOCAL) - { - DUMPI("(local)"); - } - if (decl->attr.domains & ATTR_ENUM) - { - DUMPI("(enum)"); - } - if (decl->attr.domains & ATTR_STRUCT) - { - DUMPI("(struct)"); - } - if (decl->attr.domains & ATTR_UNION) - { - DUMPI("(union)"); - } - if (decl->attr.domains & ATTR_CONST) - { - DUMPI("(const)"); - } - if (decl->attr.domains & ATTR_ERROR) - { - DUMPI("(error)"); - } - if (decl->attr.domains & ATTR_TYPEDEF) - { - DUMPI("(typedef)"); - } - // TODO attribute - DUMPEND(); - } - UNREACHABLE -} - -static void fprint_decl_list(Context *context, FILE *file, Decl **decls, int indent) -{ - VECEACH(decls, i) - { - fprint_decl_recursive(context, file, decls[i], indent); - } -} - -static void fprint_expr_list(Context *context, FILE *file, Expr **exprs, int indent) -{ - VECEACH(exprs, i) - { - fprint_expr_recursive(context, file, exprs[i], indent); - } -} - -static void fprint_asts_recursive(Context *context, FILE *file, Ast **asts, int indent) -{ - VECEACH(asts, i) - { - fprint_ast_recursive(context, file, asts[i], indent); - } -} - -static void fprint_ast_recursive(Context *context, FILE *file, Ast *ast, int indent) -{ - if (!ast) return; - switch (ast->ast_kind) - { - case AST_CT_ASSERT: - DUMP("($assert"); - DUMPEXPR(ast->ct_assert_stmt.expr); - DUMPEXPR(ast->ct_assert_stmt.message); - DUMPEND(); - case AST_ASSERT_STMT: - DUMP("(assert"); - DUMPEXPR(ast->assert_stmt.expr); - DUMPEXPR(ast->assert_stmt.message); - DUMPEND(); - case AST_COMPOUND_STMT: - if (!ast->compound_stmt.stmts) - { - DUMP("(compound)"); - return; - } - DUMP("(compound\n"); - fprint_asts_recursive(context, file, ast->compound_stmt.stmts, indent + 1); - DUMPEND(); - case AST_CT_COMPOUND_STMT: - if (!ast->compound_stmt.stmts) - { - DUMP("(ct-compound)"); - return; - } - DUMP("(ct-compound\n"); - fprint_asts_recursive(context, file, ast->ct_compound_stmt, indent + 1); - DUMPEND(); - case AST_DOCS: - DUMP("(directives"); - fprint_asts_recursive(context, file, ast->directives, indent + 1); - DUMPEND(); - case AST_DOC_DIRECTIVE: - DUMP("(doc-directive"); - DUMPEND(); - case AST_DEFINE_STMT: - DUMP("(define"); - DUMPDECL(ast->var_stmt); - DUMPEND(); - case AST_DECLARE_STMT: - DUMP("(declare"); - DUMPDECL(ast->declare_stmt); - DUMPEND(); - case AST_EXPR_STMT: - DUMP("expr"); - DUMPEXPR(ast->expr_stmt); - DUMPEND(); - case AST_WHILE_STMT: - DUMP("(while"); - DUMPEXPR(ast->while_stmt.cond); - DUMPAST(ast->while_stmt.body); - DUMPEND(); - case AST_SCOPED_STMT: - DUMP("(scoped"); - DUMPAST(ast->scoped_stmt.stmt); - DUMPEND(); - case AST_CT_FOR_STMT: - if (ast->ct_for_stmt.index.index) - { - DUMPF("($for %s, %s\n", TOKSTR(ast->ct_for_stmt.index), TOKSTR(ast->ct_for_stmt.value)); - } - else - { - DUMPF("($for %s\n", TOKSTR(ast->ct_for_stmt.value)); - } - DUMPEXPR(ast->ct_for_stmt.expr); - DUMPAST(ast->ct_for_stmt.body); - DUMPEND(); - case AST_DO_STMT: - DUMP("(do"); - DUMPAST(ast->do_stmt.body); - DUMPEXPR(ast->do_stmt.expr); - DUMPEND(); - case AST_RETURN_STMT: - if (ast->return_stmt.expr) - { - DUMP("(return"); - DUMPEXPR(ast->expr_stmt); - DUMPEND(); - } - DUMP("(return)"); - return; - case AST_BREAK_STMT: - DUMP("(break)"); - return; - case AST_NEXT_STMT: - DUMP("(next)"); - return; - case AST_CONTINUE_STMT: - DUMP("(continue)"); - return; - case AST_DEFAULT_STMT: - DUMP("(default)"); - return; - case AST_FOR_STMT: - DUMP("(for"); - DUMPEXPR(ast->for_stmt.init); - DUMPEXPR(ast->for_stmt.cond); - if (ast->for_stmt.incr) - { - DUMPEXPR(ast->for_stmt.incr); - } - else - { - DUMPI("(noincr)"); - } - DUMPAST(ast->for_stmt.body); - DUMPEND(); - case AST_FOREACH_STMT: - DUMP("(foreach"); - DUMPDECL(ast->foreach_stmt.index); - DUMPDECL(ast->foreach_stmt.variable); - DUMPEXPR(ast->foreach_stmt.enumeration); - DUMPAST(ast->foreach_stmt.body); - DUMPEND(); - case AST_IF_STMT: - DUMP("(if"); - DUMPEXPR(ast->if_stmt.cond); - DUMPAST(ast->if_stmt.then_body); - DUMPAST(ast->if_stmt.else_body); - DUMPEND(); - case AST_SWITCH_STMT: - DUMP("(switch"); - DUMPEXPR(ast->switch_stmt.cond); - DUMPASTS(ast->switch_stmt.cases); - DUMPEND(); - case AST_IF_CATCH_SWITCH_STMT: - DUMP("(if-catch-switch"); - DUMPEXPR(ast->switch_stmt.cond); - DUMPASTS(ast->switch_stmt.cases); - DUMPEND(); - case AST_CASE_STMT: - DUMP("(case"); - DUMPEXPR(ast->case_stmt.expr); - DUMPAST(ast->case_stmt.body); - DUMPEND(); - case AST_DEFER_STMT: - DUMP("(defer"); - DUMPAST(ast->defer_stmt.body); - DUMPEND(); - case AST_POISONED: - DUMP("(ast-poisoned)"); - return; - case AST_ASM_STMT: - DUMP("(asm"); - // TODO - DUMPEND(); - case AST_CT_IF_STMT: - DUMP("(ct-if"); - DUMPEXPR(ast->ct_if_stmt.expr); - DUMPAST(ast->ct_if_stmt.then); - DUMPAST(ast->ct_if_stmt.elif); - DUMPEND(); - case AST_CT_ELIF_STMT: - DUMP("(ct-elif"); - DUMPEXPR(ast->ct_elif_stmt.expr); - DUMPAST(ast->ct_elif_stmt.then); - DUMPAST(ast->ct_elif_stmt.elif); - DUMPEND(); - case AST_CT_ELSE_STMT: - DUMP("(ct-else"); - DUMPAST(ast->ct_else_stmt); - DUMPEND(); - case AST_CT_SWITCH_STMT: - DUMP("(ct-switch"); - DUMPEXPR(ast->ct_switch_stmt.cond); - DUMPASTS(ast->ct_switch_stmt.body); - DUMPEND(); - case AST_NOP_STMT: - DUMP("(nop)"); - return; - case AST_UNREACHABLE_STMT: - DUMP("(unreachable)"); - return; - case AST_VOLATILE_STMT: - DUMP("(volatile"); - DUMPAST(ast->volatile_stmt); - DUMPEND(); - } - UNREACHABLE -} -void fprint_decl(Context *context, FILE *file, Decl *dec) -{ - fprint_decl_recursive(context, file, dec, 0); -} diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 16223f3e4..1b48a6f9b 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -91,7 +91,6 @@ void compiler_parse(void) global_context_clear_errors(); parse_file(file); - TODO; //context_print_ast(context, stdout); } exit(EXIT_SUCCESS); } diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index ded0cb2fe..c96b5160e 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -79,18 +79,49 @@ typedef struct BigInt_ }; } BigInt; + typedef enum { - CONST_FLOAT, - CONST_INTEGER, - CONST_BOOL, - CONST_ENUM, - CONST_ERR, - CONST_BYTES, - CONST_STRING, - CONST_POINTER, - CONST_TYPEID, -} ConstKind; + CONST_INIT_ZERO, + CONST_INIT_STRUCT, + CONST_INIT_UNION, + CONST_INIT_VALUE, + CONST_INIT_ARRAY, + CONST_INIT_ARRAY_FULL, + CONST_INIT_ARRAY_VALUE, + } ConstInitType; + + +typedef struct ConstInitializer_ +{ + ConstInitType kind; + // Type initialized + Type *type; + union + { + struct ConstInitializer_ **init_struct; + Expr *init_value; + struct + { + struct ConstInitializer_ *element; + MemberIndex index; + } init_union; + struct + { + struct ConstInitializer_ **elements; + } init_array; + struct ConstInitializer_ **init_array_full; + struct + { + struct ConstInitializer_ *element; + ArrayIndex index; + } init_array_value; + }; +} ConstInitializer; + + + + typedef struct { @@ -121,6 +152,7 @@ typedef struct uint64_t len; } bytes; Type *typeid; + ConstInitializer *list; }; } ExprConst; @@ -708,45 +740,6 @@ typedef struct DesignatorElement_ ArrayIndex index_end; } DesignatorElement; -typedef enum -{ - CONST_INIT_ZERO, - CONST_INIT_STRUCT, - CONST_INIT_UNION, - CONST_INIT_VALUE, - CONST_INIT_ARRAY, - CONST_INIT_ARRAY_FULL, - CONST_INIT_ARRAY_VALUE, -} ConstInitType; - - -typedef struct ConstInitializer_ -{ - ConstInitType kind; - // Type initialized - Type *type; - union - { - struct ConstInitializer_ **init_struct; - Expr *init_value; - struct - { - struct ConstInitializer_ *element; - MemberIndex index; - } init_union; - struct - { - struct ConstInitializer_ **elements; - } init_array; - struct ConstInitializer_ **init_array_full; - struct - { - struct ConstInitializer_ *element; - ArrayIndex index; - } init_array_value; - }; -} ConstInitializer; - typedef struct { DesignatorElement **path; @@ -839,23 +832,6 @@ typedef struct } ExprMacroBlock; -typedef enum -{ - INITIALIZER_UNKNOWN, - INITIALIZER_DESIGNATED, - INITIALIZER_NORMAL, - INITIALIZER_CONST, -} InitializerType; - -typedef struct -{ - InitializerType init_type; - union - { - Expr** initializer_expr; - ConstInitializer *initializer; - }; -} ExprInitializer; typedef struct { @@ -990,10 +966,11 @@ struct Expr_ ExprIdentifierRaw hash_ident_expr; TypeInfo *typeid_expr; ExprBodyExpansion body_expansion_expr; - ExprInitializer initializer_expr; Decl *expr_enum; ExprCompoundLiteral expr_compound_literal; Expr** expression_list; + Expr** initializer_list; + Expr** designated_init_list; ExprScope expr_scope; ExprFuncBlock expr_block; ExprMacroBlock macro_block; @@ -1576,8 +1553,9 @@ extern Type *type_char, *type_ushort, *type_uint, *type_ulong, *type_usize; extern Type *type_iptr, *type_uptr, *type_iptrdiff, *type_uptrdiff; extern Type *type_u128, *type_i128; extern Type *type_compint, *type_compfloat; -extern Type *type_typeid, *type_anyerr, *type_typeinfo, *type_varheader; +extern Type *type_typeid, *type_anyerr, *type_typeinfo; extern Type *type_virtual, *type_virtual_generic; +extern Type *type_complist; extern const char *attribute_list[NUMBER_OF_ATTRIBUTES]; @@ -1740,7 +1718,6 @@ void context_register_external_symbol(Context *context, Decl *decl); bool context_add_import(Context *context, Path *path, Token symbol, Token alias, bool private_import); bool context_set_module_from_filename(Context *context); bool context_set_module(Context *context, Path *path, TokenId *generic_parameters, bool is_private); -void context_print_ast(Context *context, FILE *file); #pragma mark --- Decl functions @@ -1753,7 +1730,7 @@ Decl *decl_new_generated_var(const char *name, Type *type, VarDeclKind kind, Sou #define DECL_NEW_VAR(_type, _kind, _vis) decl_new_var(context->tok.id, _type, _kind, _vis) void decl_set_external_name(Decl *decl); const char *decl_to_name(Decl *decl); -const char *decl_var_to_string(VarDeclKind kind); + static inline Decl *decl_raw(Decl *decl); static inline bool decl_ok(Decl *decl) { return !decl || decl->decl_kind != DECL_POISONED; } static inline bool decl_poison(Decl *decl) { decl->decl_kind = DECL_POISONED; decl->resolve_status = RESOLVE_DONE; return false; } @@ -1815,7 +1792,7 @@ void expr_const_set_int(ExprConst *expr, uint64_t v, TypeKind kind); void expr_const_set_float(ExprConst *expr, Real d, TypeKind kind); void expr_const_set_bool(ExprConst *expr, bool b); void expr_const_set_null(ExprConst *expr); -void expr_const_fprint(FILE *__restrict file, ExprConst *expr); + bool expr_const_int_overflowed(const ExprConst *expr); bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp op); bool expr_const_will_overflow(const ExprConst *expr, TypeKind kind); @@ -1824,6 +1801,11 @@ void expr_insert_deref(Expr *expr); Expr *expr_variable(Decl *decl); bool expr_is_constant_eval(Expr *expr); const char *expr_const_to_error_string(const ExprConst *expr); +static inline bool expr_is_init_list(Expr *expr) +{ + ExprKind kind = expr->expr_kind; + return kind == EXPR_DESIGNATED_INITIALIZER_LIST || kind == EXPR_INITIALIZER_LIST; +} static inline void expr_set_type(Expr *expr, Type *type) { assert(type); @@ -1831,10 +1813,6 @@ static inline void expr_set_type(Expr *expr, Type *type) expr->original_type = type; } -void fprint_decl(Context *context, FILE *file, Decl *dec); -void fprint_type_info_recursive(Context *context, FILE *file, TypeInfo *type_info, int indent); -void fprint_expr_recursive(Context *context, FILE *file, Expr *expr, int indent); - #pragma mark --- Lexer functions @@ -1871,8 +1849,6 @@ bool parse_file(File *file); Path *path_create_from_string(const char *string, size_t len, SourceSpan span); Path *path_find_parent_path(Path *path); -const char *resolve_status_to_string(ResolveStatus status); - #define SEMA_TOKEN_ERROR(_tok, ...) sema_error_range(source_span_from_token_id(_tok.id), __VA_ARGS__) #define SEMA_TOKID_ERROR(_tok_id, ...) sema_error_range(source_span_from_token_id(_tok_id), __VA_ARGS__) #define SEMA_ERROR(_node, ...) sema_error_range((_node)->span, __VA_ARGS__) @@ -2176,9 +2152,7 @@ static inline bool type_convert_will_trunc(Type *destination, Type *source) UnaryOp unaryop_from_token(TokenType type); -TokenType unaryop_to_token(UnaryOp type); PostUnaryOp post_unaryop_from_token(TokenType type); -TokenType postunaryop_to_token(PostUnaryOp type); BinaryOp binaryop_from_token(TokenType type); BinaryOp binaryop_assign_base_op(BinaryOp assign_binary_op); TokenType binaryop_to_token(BinaryOp type); diff --git a/src/compiler/context.c b/src/compiler/context.c index b24df2d53..d72574c08 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -61,8 +61,8 @@ static bool filename_to_module_in_buffer(const char *path) if (path[i] == '/') last_slash = i; if (path[i] == '.') last_dot = i; } - int namelen = last_dot - last_slash - 1; - if (namelen < 1) return false; + int name_len = last_dot - last_slash - 1; + if (name_len < 1) return false; scratch_buffer_clear(); for (int i = last_slash + 1; i < last_dot; i++) { @@ -280,30 +280,3 @@ bool context_add_import(Context *context, Path *path, Token token, Token alias, return true; } -void context_print_ast(Context *context, FILE *file) -{ - VECEACH(context->enums, i) - { - fprint_decl(context, file, context->enums[i]); - } - VECEACH(context->global_decls, i) - { - fprint_decl(context, file, context->global_decls[i]); - } - VECEACH(context->vars, i) - { - fprint_decl(context, file, context->vars[i]); - } - VECEACH(context->types, i) - { - fprint_decl(context, file, context->types[i]); - } - VECEACH(context->functions, i) - { - fprint_decl(context, file, context->functions[i]); - } - VECEACH(context->ct_ifs, i) - { - fprint_decl(context, file, context->ct_ifs[i]); - } -} diff --git a/src/compiler/copying.c b/src/compiler/copying.c index e80b6e710..4d7d5dc6e 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -206,7 +206,10 @@ Expr *copy_expr(Expr *source_expr) MACRO_COPY_EXPR(expr->access_expr.parent); return expr; case EXPR_INITIALIZER_LIST: - MACRO_COPY_EXPR_LIST(expr->initializer_expr.initializer_expr); + MACRO_COPY_EXPR_LIST(expr->initializer_list); + return expr; + case EXPR_DESIGNATED_INITIALIZER_LIST: + MACRO_COPY_EXPR_LIST(expr->designated_init_list); return expr; case EXPR_EXPRESSION_LIST: MACRO_COPY_EXPR_LIST(expr->expression_list); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index e10990375..ca612a44d 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -203,6 +203,7 @@ typedef enum EXPR_IDENTIFIER, EXPR_FLATPATH, EXPR_INITIALIZER_LIST, + EXPR_DESIGNATED_INITIALIZER_LIST, EXPR_LEN, EXPR_PLACEHOLDER, EXPR_POST_UNARY, @@ -224,6 +225,20 @@ typedef enum EXPR_NOP, } ExprKind; +typedef enum +{ + CONST_FLOAT, + CONST_INTEGER, + CONST_BOOL, + CONST_ENUM, + CONST_ERR, + CONST_BYTES, + CONST_STRING, + CONST_POINTER, + CONST_TYPEID, + CONST_LIST, +} ConstKind; + typedef enum { DESIGNATOR_FIELD, @@ -535,6 +550,7 @@ typedef enum TYPE_ARRAY, TYPE_SUBARRAY, TYPE_INFERRED_ARRAY, + TYPE_UNTYPED_LIST, TYPE_TYPEINFO, TYPE_VECTOR, TYPE_VIRTUAL, @@ -542,7 +558,7 @@ typedef enum TYPE_LAST = TYPE_VIRTUAL_ANY } TypeKind; -#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_POISONED +#define CT_TYPES TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: case TYPE_UNTYPED_LIST: case TYPE_POISONED #define ALL_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128: \ case TYPE_U8: case TYPE_U16: case TYPE_U32: case TYPE_U64: case TYPE_U128: case TYPE_IXX #define ALL_SIGNED_INTS TYPE_I8: case TYPE_I16: case TYPE_I32: case TYPE_I64: case TYPE_I128 diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 45080a9d8..3fac9df12 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -30,7 +30,7 @@ static void header_print_type(FILE *file, Type *type) { switch (type->type_kind) { - case TYPE_POISONED: + case CT_TYPES: UNREACHABLE case TYPE_BITSTRUCT: TODO @@ -111,7 +111,6 @@ static void header_print_type(FILE *file, Type *type) case TYPE_TYPEDEF: break; case TYPE_STRLIT: - case TYPE_INFERRED_ARRAY: UNREACHABLE case TYPE_ARRAY: break; @@ -120,8 +119,6 @@ static void header_print_type(FILE *file, Type *type) break; case TYPE_SUBARRAY: break; - case TYPE_TYPEINFO: - break; case TYPE_VECTOR: break; } diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 9d067f54c..4b64c70f6 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -241,7 +241,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ static LLVMValueRef llvm_emit_const_initializer_simple(GenContext *c, Expr *expr, bool *modified) { - Expr **elements = expr->initializer_expr.initializer_expr; + Expr **elements = expr->initializer_list; unsigned element_count = vec_size(elements); LLVMValueRef* values = malloc_arena(element_count * sizeof(LLVMValueRef)); Type *expr_type = expr->type->canonical; @@ -271,20 +271,6 @@ static LLVMValueRef llvm_emit_const_initializer_simple(GenContext *c, Expr *expr return LLVMConstNamedStruct(llvm_get_type(c, expr_type), values, element_count); } -LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified) -{ - switch (expr->initializer_expr.init_type) - { - case INITIALIZER_UNKNOWN: - case INITIALIZER_DESIGNATED: - UNREACHABLE - case INITIALIZER_CONST: - return llvm_emit_const_initializer(c, expr->initializer_expr.initializer, modified); - case INITIALIZER_NORMAL: - return llvm_emit_const_initializer_simple(c, expr, modified); - } - UNREACHABLE -} static void gencontext_emit_global_variable_definition(GenContext *c, Decl *decl) { @@ -352,9 +338,9 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) Expr *init_expr = decl->var.init_expr; if (init_expr) { - if (init_expr->expr_kind == EXPR_INITIALIZER_LIST) + if (init_expr->expr_kind == EXPR_CONST && init_expr->const_expr.const_kind == CONST_LIST) { - init_value = llvm_emit_const_aggregate(c, init_expr, &modified); + init_value = llvm_emit_const_initializer(c, init_expr->const_expr.list, &modified); } else { diff --git a/src/compiler/llvm_codegen_c_abi_x86.c b/src/compiler/llvm_codegen_c_abi_x86.c index e5a278220..c79f3b843 100644 --- a/src/compiler/llvm_codegen_c_abi_x86.c +++ b/src/compiler/llvm_codegen_c_abi_x86.c @@ -108,19 +108,17 @@ static bool x86_should_return_type_in_reg(Type *type) switch (type->type_kind) { case TYPE_VECTOR: - case TYPE_POISONED: case TYPE_VOID: case TYPE_FUNC: case TYPE_TYPEDEF: - case TYPE_TYPEINFO: case TYPE_DISTINCT: case TYPE_ENUM: case TYPE_STRLIT: - case TYPE_INFERRED_ARRAY: case TYPE_ERRTYPE: case TYPE_TYPEID: case TYPE_ANYERR: case TYPE_BITSTRUCT: + case CT_TYPES: UNREACHABLE case ALL_INTS: case ALL_FLOATS: diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index b1dea62bb..438f11cb3 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -12,7 +12,7 @@ static inline void llvm_emit_inc_dec_change(GenContext *c, bool use_mod, BEValue static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Expr *expr); static inline LLVMValueRef llvm_emit_subscript_addr_with_base_new(GenContext *c, BEValue *parent, BEValue *index, SourceLocation *loc); static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, uint64_t offset, DesignatorElement** current, DesignatorElement **last, Expr *expr, BEValue *emitted_value); - +static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr); LLVMValueRef llvm_emit_is_no_error_value(GenContext *c, BEValue *value) { llvm_value_rvalue(c, value); @@ -693,7 +693,18 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_ value->type = to_type; return; case CAST_SABOOL: - TODO + llvm_value_fold_failable(c, value); + if (llvm_value_is_addr(value)) + { + value->value = LLVMBuildStructGEP(c->builder, value->value, 1, ""); + } + else + { + value->value = LLVMBuildExtractValue(c->builder, value->value, 1, ""); + } + value->type = type_usize->canonical; + llvm_value_rvalue(c, value); + llvm_emit_int_comp_zero(c, value, value, BINARYOP_NE); break; } value->type = to_type; @@ -778,7 +789,8 @@ static inline void llvm_emit_initialize_reference_temporary_const(GenContext *c, Type *canonical = expr->type->canonical; - LLVMValueRef value = llvm_emit_const_aggregate(c, expr, &modified); + assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST); + LLVMValueRef value = llvm_emit_const_initializer(c, expr->const_expr.list, &modified); // Create a global const. LLVMTypeRef type = modified ? LLVMTypeOf(value) : llvm_get_type(c, canonical); @@ -895,7 +907,8 @@ static void llvm_emit_inititialize_reference_const(GenContext *c, BEValue *ref, } static inline void llvm_emit_initialize_reference_const(GenContext *c, BEValue *ref, Expr *expr) { - ConstInitializer *initializer = expr->initializer_expr.initializer; + assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST); + ConstInitializer *initializer = expr->const_expr.list; // Make sure we have an address. llvm_value_addr(c, ref); @@ -908,7 +921,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r { // Getting ready to initialize, get the real type. Type *real_type = type_lowering(ref->type); - Expr **elements = expr->initializer_expr.initializer_expr; + Expr **elements = expr->initializer_list; // Make sure we have an address. llvm_value_addr(c, ref); @@ -957,7 +970,12 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r llvm_value_set_address_align(&pointer, value, element->type, ref->alignment); } // If this is an initializer, we want to actually run the initialization recursively. - if (element->expr_kind == EXPR_INITIALIZER_LIST) + if (element->expr_kind == EXPR_CONST && element->const_expr.const_kind == CONST_LIST) + { + llvm_emit_const_initialize_reference(c, &pointer, element); + continue; + } + if (expr_is_init_list(element)) { llvm_emit_initialize_reference(c, &pointer, element); continue; @@ -1008,7 +1026,12 @@ static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, uint64_ llvm_store_bevalue(c, ref, emitted_value); return; } - if (expr->expr_kind == EXPR_INITIALIZER_LIST) + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) + { + llvm_emit_const_initialize_reference(c, ref, expr); + return; + } + if (expr_is_init_list(expr)) { llvm_emit_initialize_reference(c, ref, expr); return; @@ -1063,7 +1086,7 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa { // Getting ready to initialize, get the real type. Type *real_type = type_lowering(ref->type); - Expr **elements = expr->initializer_expr.initializer_expr; + Expr **elements = expr->designated_init_list; assert(vec_size(elements)); // Make sure we have an address. @@ -1081,6 +1104,29 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa } } +/** + * Initialize a constant aggregate type. + */ +static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr) +{ + assert(expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST); + ConstInitializer *initializer = expr->const_expr.list; + if (initializer->kind == CONST_INIT_ZERO) + { + // In case of a zero, optimize. + llvm_emit_memclear(c, ref); + return; + } + // In case of small const initializers, or full arrays - use copy. + if (initializer->kind == CONST_INIT_ARRAY_FULL || type_size(expr->type) <= 32) + { + llvm_emit_initialize_reference_temporary_const(c, ref, expr); + return; + } + llvm_emit_initialize_reference_const(c, ref, expr); + return; +} + /** * Initialize an aggregate type. * @@ -1092,34 +1138,12 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa */ static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *ref, Expr *expr) { - // In the case of a const, we have some optimizations: - if (expr->initializer_expr.init_type == INITIALIZER_CONST) + switch (expr->expr_kind) { - ConstInitializer *initializer = expr->initializer_expr.initializer; - if (initializer->kind == CONST_INIT_ZERO) - { - // In case of a zero, optimize. - llvm_emit_memclear(c, ref); - return; - } - // In case of small const initializers, or full arrays - use copy. - if (initializer->kind == CONST_INIT_ARRAY_FULL || type_size(expr->type) <= 32) - { - llvm_emit_initialize_reference_temporary_const(c, ref, expr); - return; - } - } - - switch (expr->initializer_expr.init_type) - { - case INITIALIZER_CONST: - // Just clear memory - llvm_emit_initialize_reference_const(c, ref, expr); - break; - case INITIALIZER_NORMAL: + case EXPR_INITIALIZER_LIST: llvm_emit_initialize_reference_list(c, ref, expr); break; - case INITIALIZER_DESIGNATED: + case EXPR_DESIGNATED_INITIALIZER_LIST: llvm_emit_initialize_reference_designated(c, ref, expr); break; default: @@ -2613,6 +2637,12 @@ static LLVMValueRef llvm_emit_real(LLVMTypeRef type, Real f) return LLVMConstRealOfStringAndSize(type, global_context.scratch_buffer, global_context.scratch_buffer_len); } +static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr) +{ + llvm_value_set_address(value, llvm_emit_alloca_aligned(c, expr->type, "literal"), expr->type); + llvm_emit_initialize_reference_const(c, value, expr); +} + static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr) { Type *type = type_reduced_from_expr(expr)->canonical; @@ -2644,6 +2674,9 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr) llvm_value_set(be_value, llvm_const_int(c, type, bigint_as_signed(&expr->const_expr.i)), type); } return; + case CONST_LIST: + llvm_emit_const_initializer_list_expr(c, be_value, expr); + return; case CONST_FLOAT: llvm_value_set(be_value, llvm_emit_real(llvm_get_type(c, type), expr->const_expr.f), type); return; @@ -3545,7 +3578,12 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue } BEValue value; if (expr->expr_kind == EXPR_COMPOUND_LITERAL) expr = expr->expr_compound_literal.initializer; - if (expr->expr_kind == EXPR_INITIALIZER_LIST) + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) + { + llvm_emit_const_initialize_reference(c, ref, expr); + value = *ref; + } + else if (expr_is_init_list(expr)) { llvm_emit_initialize_reference(c, ref, expr); value = *ref; @@ -3595,6 +3633,7 @@ static inline void gencontext_emit_failable(GenContext *context, BEValue *be_val llvm_value_set(be_value, LLVMGetUndef(llvm_get_type(context, expr->type)), expr->type); } + static inline void llvm_emit_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr) { llvm_value_set_address(value, llvm_emit_alloca_aligned(c, expr->type, "literal"), expr->type); @@ -3799,6 +3838,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_COMPOUND_LITERAL: UNREACHABLE case EXPR_INITIALIZER_LIST: + case EXPR_DESIGNATED_INITIALIZER_LIST: llvm_emit_initializer_list_expr(c, value, expr); return; case EXPR_EXPR_BLOCK: diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index a8102066c..a24aef5ac 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -236,8 +236,7 @@ void llvm_emit_debug_local_var(GenContext *c, Decl *var); void llvm_emit_debug_global_var(GenContext *c, Decl *global); void llvm_emit_defer(GenContext *c, AstId defer_start, AstId defer_end); void llvm_emit_extern_decl(GenContext *context, Decl *decl); - -LLVMValueRef llvm_emit_const_aggregate(GenContext *c, Expr *expr, bool *modified); +LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_init, bool *modified); void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr); void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type); void llvm_emit_global_variable_init(GenContext *c, Decl *decl); diff --git a/src/compiler/number.c b/src/compiler/number.c index 61d751f45..1bc43a9e9 100644 --- a/src/compiler/number.c +++ b/src/compiler/number.c @@ -5,46 +5,6 @@ #include "compiler_internal.h" -void expr_const_fprint(FILE *__restrict file, ExprConst *expr) -{ - switch (expr->const_kind) - { - case CONST_POINTER: - fprintf(file, "null"); - break; - case CONST_BOOL: - fprintf(file, expr->b ? "true" : "false"); - break; - case CONST_INTEGER: - bigint_fprint(file, &expr->i, 10); - break; - case CONST_FLOAT: -#if LONG_DOUBLE - fprintf(file, "%Lg", expr->f); -#else - fprintf(file, "%g", expr->f); -#endif - break; - case CONST_STRING: - fprintf(file, "%.*s", expr->string.len, expr->string.chars); - break; - case CONST_BYTES: - fprintf(file, "[byte data]"); - break; - case CONST_ENUM: - fprintf(file, "%s", expr->enum_val->name); - break; - case CONST_ERR: - fprintf(file, "%s", expr->err_val->name); - break; - case CONST_TYPEID: - fprintf(file, "%s", expr->typeid->name); - break; - - } - -} - void expr_const_set_int(ExprConst *expr, uint64_t v, TypeKind kind) { if (type_kind_is_signed(kind)) @@ -293,6 +253,8 @@ const char *expr_const_to_error_string(const ExprConst *expr) return expr->err_val->name; case CONST_TYPEID: return expr->typeid->name; + case CONST_LIST: + return "constant list"; } UNREACHABLE } diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index e6713c236..d694528a7 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -50,12 +50,8 @@ static Expr *parse_precedence(Context *context, Precedence precedence) return parse_precedence_with_left_side(context, left_side, precedence); } -static inline Expr *parse_expr_or_initializer_list(Context *context) +Expr *parse_expr_or_initializer_list(Context *context) { - if (TOKEN_IS(TOKEN_LBRACE)) - { - return parse_initializer_list(context); - } return parse_expr(context); } @@ -501,10 +497,6 @@ Expr *parse_initializer(Context *context) advance(context); return expr; } - if (TOKEN_IS(TOKEN_LBRACE)) - { - return parse_initializer_list(context); - } return parse_expr(context); } @@ -522,15 +514,47 @@ Expr *parse_initializer(Context *context) * @param elements * @return */ -Expr *parse_initializer_list(Context *context) +Expr *parse_initializer_list(Context *context, Expr *left) { + assert(!left && "Unexpected left hand side"); Expr *initializer_list = EXPR_NEW_TOKEN(EXPR_INITIALIZER_LIST, context->tok); - initializer_list->initializer_expr.init_type = INITIALIZER_UNKNOWN; - CONSUME_OR(TOKEN_LBRACE, poisoned_expr); + advance_and_verify(context, TOKEN_LBRACE); if (!try_consume(context, TOKEN_RBRACE)) { - if (!parse_arg_list(context, &initializer_list->initializer_expr.initializer_expr, TOKEN_RBRACE, NULL)) return poisoned_expr; + Expr **exprs = NULL; + if (!parse_arg_list(context, &exprs, TOKEN_RBRACE, NULL)) return poisoned_expr; + int designated = -1; + VECEACH(exprs, i) + { + Expr *expr = exprs[i]; + if (expr->expr_kind == EXPR_DESIGNATOR) + { + if (designated == 0) + { + SEMA_ERROR(expr, "Designated initialization with '[] = ...' and '.param = ...' cannot be mixed with normal initialization."); + return poisoned_expr; + } + designated = 1; + continue; + } + if (designated == 1) + { + SEMA_ERROR(expr, "Normal initialization cannot be mixed with designated initialization."); + return poisoned_expr; + } + designated = 0; + } CONSUME_OR(TOKEN_RBRACE, poisoned_expr); + RANGE_EXTEND_PREV(initializer_list); + if (designated == 1) + { + initializer_list->designated_init_list = exprs; + initializer_list->expr_kind = EXPR_DESIGNATED_INITIALIZER_LIST; + } + else + { + initializer_list->initializer_list = exprs; + } } RANGE_EXTEND_PREV(initializer_list); return initializer_list; @@ -557,21 +581,14 @@ static Expr *parse_binary(Context *context, Expr *left_side) advance(context); Expr *right_side; - if (TOKEN_IS(TOKEN_LBRACE) && operator_type == TOKEN_EQ) + // Assignment operators have precedence right -> left. + if (rules[operator_type].precedence == PREC_ASSIGNMENT) { - ASSIGN_EXPR_ELSE(right_side, parse_initializer_list(context), poisoned_expr); + ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr); } else { - // Assignment operators have precedence right -> left. - if (rules[operator_type].precedence == PREC_ASSIGNMENT) - { - ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, PREC_ASSIGNMENT), poisoned_expr); - } - else - { - ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr); - } + ASSIGN_EXPR_ELSE(right_side, parse_precedence(context, rules[operator_type].precedence + 1), poisoned_expr); } Expr *expr = EXPR_NEW_EXPR(EXPR_BINARY, left_side); @@ -1265,7 +1282,8 @@ Expr *parse_type_compound_literal_expr_after_type(Context *context, TypeInfo *ty { Expr *expr = expr_new(EXPR_COMPOUND_LITERAL, type_info->span); expr->expr_compound_literal.type_info = type_info; - ASSIGN_EXPR_ELSE(expr->expr_compound_literal.initializer, parse_initializer_list(context), poisoned_expr); + EXPECT_OR(TOKEN_LBRACE, poisoned_expr); + ASSIGN_EXPR_ELSE(expr->expr_compound_literal.initializer, parse_initializer_list(context, NULL), poisoned_expr); RANGE_EXTEND_PREV(expr); return expr; } @@ -1423,4 +1441,6 @@ ParseRule rules[TOKEN_EOF + 1] = { [TOKEN_CT_NAMEOF] = { parse_ct_call, NULL, PREC_NONE }, [TOKEN_CT_QNAMEOF] = { parse_ct_call, NULL, PREC_NONE }, [TOKEN_CT_TYPEOF] = { parse_typeof_expr, NULL, PREC_NONE }, + + [TOKEN_LBRACE] = { parse_initializer_list, NULL, PREC_NONE }, }; diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index 7b1a9fad8..31a44ff31 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -39,7 +39,6 @@ Expr *parse_try_expr_after_try(Context *context, bool is_try); TypeInfo *parse_type(Context *context); TypeInfo *parse_type_with_base(Context *context, TypeInfo *type_info); Expr* parse_constant_expr(Context *context); -Expr *parse_initializer_list(Context *context); Expr *parse_initializer(Context *context); void parse_imports(Context *context); Decl *parse_decl(Context *context); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index dabe61549..d3976caf9 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -411,6 +411,7 @@ CastKind cast_to_bool_kind(Type *type) case TYPE_TYPEINFO: case TYPE_VECTOR: case TYPE_BITSTRUCT: + case TYPE_UNTYPED_LIST: return CAST_ERROR; } UNREACHABLE @@ -493,6 +494,9 @@ bool cast_may_explicit(Type *from_type, Type *to_type) return to_kind == TYPE_POINTER; case TYPE_VECTOR: return type_is_structurally_equivalent(type_get_array(from->vector.base, from->vector.len), to); + case TYPE_UNTYPED_LIST: + REMINDER("Look at untyped list explicit conversions"); + return false; } UNREACHABLE } @@ -808,6 +812,32 @@ bool cast_implicit_bit_width(Expr *expr, Type *to_type) return cast_implicit(expr, to_type); } +static inline bool subarray_to_bool(Expr *expr) +{ + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) + { + ConstInitializer *list = expr->const_expr.list; + switch (list->kind) + { + case CONST_INIT_ZERO: + expr_const_set_bool(&expr->const_expr, false); + return true; + case CONST_INIT_ARRAY: + expr_const_set_bool(&expr->const_expr, vec_size(list->init_array.elements) > 0); + return true; + case CONST_INIT_ARRAY_FULL: + expr_const_set_bool(&expr->const_expr, vec_size(list->init_array_full) > 0); + return true; + case CONST_INIT_STRUCT: + case CONST_INIT_UNION: + case CONST_INIT_VALUE: + case CONST_INIT_ARRAY_VALUE: + break; + } + } + return insert_cast(expr, CAST_SABOOL, type_bool); +} + bool cast(Expr *expr, Type *to_type) { Type *from_type = type_flatten(expr->type->canonical); @@ -901,6 +931,7 @@ bool cast(Expr *expr, Type *to_type) break; case TYPE_SUBARRAY: if (canonical->type_kind == TYPE_POINTER) return insert_cast(expr, CAST_SAPTR, canonical); + if (canonical->type_kind == TYPE_BOOL) return subarray_to_bool(expr); break; case TYPE_VECTOR: TODO diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8d325a9c3..0ad66e444 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -586,15 +586,13 @@ static inline bool sema_analyse_distinct(Context *context, Decl *decl) decl->distinct_decl.base_type = base; switch (base->type_kind) { - case TYPE_POISONED: case TYPE_STRLIT: case TYPE_IXX: case TYPE_FXX: case TYPE_FUNC: case TYPE_TYPEDEF: case TYPE_DISTINCT: - case TYPE_INFERRED_ARRAY: - case TYPE_TYPEINFO: + case CT_TYPES: UNREACHABLE return false; case TYPE_VIRTUAL_ANY: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index c2de8b045..2a4d137ba 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -9,6 +9,12 @@ * - Disallow jumping in and out of an expression block. */ +static inline void expr_set_as_const_list(Expr *expr, ConstInitializer *list) +{ + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_LIST; + expr->const_expr.list = list; +} static inline bool sema_cast_rvalue(Context *context, Type *to, Expr *expr); int BINOP_PREC_REQ[BINARYOP_LAST] = @@ -527,20 +533,21 @@ bool expr_is_constant_eval(Expr *expr) return expr_is_constant_eval(expr->expr_compound_literal.initializer); case EXPR_INITIALIZER_LIST: { - Expr** init_exprs = expr->initializer_expr.initializer_expr; - switch (expr->initializer_expr.init_type) + Expr** init_exprs = expr->initializer_list; + VECEACH(init_exprs, i) { - case INITIALIZER_NORMAL: - { - VECEACH(init_exprs, i) - { - if (!expr_is_constant_eval(init_exprs[i])) return false; - } - return true; - } - default: - return false; + if (!expr_is_constant_eval(init_exprs[i])) return false; } + return true; + } + case EXPR_DESIGNATED_INITIALIZER_LIST: + { + Expr** init_exprs = expr->designated_init_list; + VECEACH(init_exprs, i) + { + if (!expr_is_constant_eval(init_exprs[i])) return false; + } + return true; } default: return false; @@ -2635,10 +2642,10 @@ static void sema_create_const_initializer_value(ConstInitializer *const_init, Ex { // Possibly this is already a const initializers, in that case // overwrite what is inside, eg [1] = { .a = 1 } - if (value->expr_kind == EXPR_INITIALIZER_LIST && value->initializer_expr.init_type == INITIALIZER_CONST) + if (value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_LIST) { - *const_init = *value->initializer_expr.initializer; - value->initializer_expr.initializer = const_init; + *const_init = *value->const_expr.list; + value->const_expr.list = const_init; return; } const_init->init_value = value; @@ -2648,7 +2655,8 @@ static void sema_create_const_initializer_value(ConstInitializer *const_init, Ex static bool is_empty_initializer_list(Expr *value) { - return value->initializer_expr.init_type == INITIALIZER_CONST && value->initializer_expr.initializer->kind == CONST_INIT_ZERO; + return value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_LIST + && value->const_expr.list->kind == CONST_INIT_ZERO; } static void sema_create_const_initializer(ConstInitializer *const_init, Expr *initializer); @@ -2908,7 +2916,7 @@ static void sema_create_const_initializer(ConstInitializer *const_init, Expr *in const_init->type = type_flatten(initializer->type); // Loop through the initializers. - Expr **init_expressions = initializer->initializer_expr.initializer_expr; + Expr **init_expressions = initializer->initializer_list; VECEACH(init_expressions, i) { Expr *expr = init_expressions[i]; @@ -2918,80 +2926,9 @@ static void sema_create_const_initializer(ConstInitializer *const_init, Expr *in } } -static void debug_dump_const_initializer(ConstInitializer *init, const char *name, unsigned indent) -{ - for (unsigned i = 0; i < indent; i++) printf(" "); - if (name) - { - printf("%s : %s", name, init->type->name ? init->type->name : "WTF"); - } - else - { - printf("%s", init->type->name ? init->type->name : "WTF"); - } - switch (init->kind) - { - case CONST_INIT_ZERO: - printf(" = 0\n"); - return; - case CONST_INIT_UNION: - { - printf(" ->\n"); - Decl** members = init->type->decl->strukt.members; - debug_dump_const_initializer(init->init_union.element, members[init->init_union.index]->name, indent + 1); - return; - } - case CONST_INIT_STRUCT: - { - printf(" ->\n"); - Decl** members = init->type->decl->strukt.members; - unsigned member_count = vec_size(members); - for (unsigned i = 0; i < member_count; i++) - { - debug_dump_const_initializer(init->init_struct[i], members[i]->name, indent + 1); - } - return; - } - case CONST_INIT_ARRAY_VALUE: - { - printf(" [%llu] ->\n", (unsigned long long)init->init_array_value.index); - debug_dump_const_initializer(init->init_array_value.element, "", indent + 1); - return; - } - case CONST_INIT_VALUE: - { - assert(init->init_value->expr_kind == EXPR_CONST); - printf(" = "); - expr_const_fprint(stdout, &init->init_value->const_expr); - puts(""); - return; - } - case CONST_INIT_ARRAY: - printf(" [//] ->\n"); - { - VECEACH(init->init_array.elements, i) - { - debug_dump_const_initializer(init->init_array.elements[i], NULL, indent + 1); - } - } - return; - case CONST_INIT_ARRAY_FULL: - printf(" [: ->\n"); - { - VECEACH(init->init_array_full, i) - { - debug_dump_const_initializer(init->init_array_full[i], NULL, indent + 1); - } - } - return; - - } - UNREACHABLE -} - static bool sema_expr_analyse_designated_initializer(Context *context, Type *assigned, Expr *initializer) { - Expr **init_expressions = initializer->initializer_expr.initializer_expr; + Expr **init_expressions = initializer->designated_init_list; Type *original = assigned->canonical; bool is_structlike = type_is_structlike(assigned->canonical); @@ -3020,11 +2957,9 @@ static bool sema_expr_analyse_designated_initializer(Context *context, Type *ass { ConstInitializer *const_init = MALLOC(sizeof(ConstInitializer)); sema_create_const_initializer(const_init, initializer); - initializer->initializer_expr.init_type = INITIALIZER_CONST; - initializer->initializer_expr.initializer = const_init; + expr_set_as_const_list(initializer, const_init); return true; } - initializer->initializer_expr.init_type = INITIALIZER_DESIGNATED; return true; } @@ -3037,9 +2972,8 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context, initializer->pure = true; initializer->constant = true; - Expr **elements = initializer->initializer_expr.initializer_expr; + Expr **elements = initializer->initializer_list; Decl **members = assigned->strukt.members; - initializer->initializer_expr.init_type = INITIALIZER_NORMAL; unsigned size = vec_size(elements); unsigned expected_members = vec_size(members); @@ -3093,10 +3027,9 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context, VECEACH(elements, i) { Expr *expr = elements[i]; - if (expr->expr_kind == EXPR_INITIALIZER_LIST) + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) { - assert(expr->constant); - inits[i] = expr->initializer_expr.initializer; + inits[i] = expr->const_expr.list; continue; } ConstInitializer *element_init = MALLOC(sizeof(ConstInitializer)); @@ -3104,8 +3037,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(Context *context, inits[i] = element_init; } const_init->init_struct = inits; - initializer->initializer_expr.init_type = INITIALIZER_CONST; - initializer->initializer_expr.initializer = const_init; + expr_set_as_const_list(initializer, const_init); } // 7. Done! @@ -3122,14 +3054,11 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T initializer->pure = true; initializer->constant = true; - Expr **elements = initializer->initializer_expr.initializer_expr; - - assert((assigned->type_kind == TYPE_ARRAY) && "The other types are not done yet."); + Expr **elements = initializer->initializer_list; Type *inner_type = type_get_indexed_type(assigned); assert(inner_type); - initializer->initializer_expr.init_type = INITIALIZER_NORMAL; unsigned size = vec_size(elements); unsigned expected_members = assigned->array.len; if (assigned->type_kind != TYPE_ARRAY) expected_members = size; @@ -3171,10 +3100,9 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T VECEACH(elements, i) { Expr *expr = elements[i]; - if (expr->expr_kind == EXPR_INITIALIZER_LIST) + if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_LIST) { - assert(expr->constant); - inits[i] = expr->initializer_expr.initializer; + inits[i] = expr->const_expr.list; continue; } ConstInitializer *element_init = MALLOC(sizeof(ConstInitializer)); @@ -3182,17 +3110,58 @@ static inline bool sema_expr_analyse_array_plain_initializer(Context *context, T inits[i] = element_init; } const_init->init_array_full = inits; - initializer->initializer_expr.init_type = INITIALIZER_CONST; - initializer->initializer_expr.initializer = const_init; + expr_set_as_const_list(initializer, const_init); } // 7. Done! return true; } +static inline bool sema_expr_analyse_untyped_initializer(Context *context, Expr *initializer) +{ + initializer->pure = true; + initializer->constant = true; + + Expr **elements = initializer->initializer_list; + + unsigned size = vec_size(elements); + + Type *element_type = NULL; + bool no_common_elements = false; + VECEACH(elements, i) + { + Expr *element = elements[i]; + if (!sema_analyse_expr(context, NULL, element)) return false; + initializer->failable |= element->failable; + initializer->pure &= element->pure; + initializer->constant &= element->constant; + if (no_common_elements) continue; + if (element_type == NULL) + { + element_type = element->type; + continue; + } + element_type = type_find_max_type(element->type, element_type); + if (!element_type) no_common_elements = true; + } + TODO +} + static inline bool sema_expr_analyse_initializer(Context *context, Type *external_type, Type *assigned, Expr *expr) { - Expr **init_expressions = expr->initializer_expr.initializer_expr; + // Note at this point this we either have + // EXPR_DESIGNATED_INITIALIZER_LIST + // or EXPR_INITIALIZER_LIST + + if (expr->expr_kind == EXPR_DESIGNATED_INITIALIZER_LIST) + { + expr_set_type(expr, external_type); + return sema_expr_analyse_designated_initializer(context, assigned, expr); + } + + assert(expr->expr_kind == EXPR_INITIALIZER_LIST); + + Expr **init_expressions = expr->initializer_list; unsigned init_expression_count = vec_size(init_expressions); @@ -3200,32 +3169,26 @@ static inline bool sema_expr_analyse_initializer(Context *context, Type *externa if (init_expression_count == 0) { external_type = sema_type_lower_by_size(external_type, 0); - assigned = sema_type_lower_by_size(assigned, 0); expr_set_type(expr, external_type); ConstInitializer *initializer = CALLOCS(ConstInitializer); initializer->kind = CONST_INIT_ZERO; initializer->type = type_flatten(expr->type); - expr->initializer_expr.init_type = INITIALIZER_CONST; - expr->initializer_expr.initializer = initializer; + expr_set_as_const_list(expr, initializer); expr->constant = true; expr->pure = true; return true; } - // 2. Check if we might have a designated initializer - // this means that in this case we're actually not resolving macros here. - if (init_expressions[0]->expr_kind == EXPR_DESIGNATOR) - { - expr_set_type(expr, external_type); - return sema_expr_analyse_designated_initializer(context, assigned, expr); - } - external_type = sema_type_lower_by_size(external_type, init_expression_count); assigned = sema_type_lower_by_size(assigned, init_expression_count); expr_set_type(expr, external_type); + if (external_type == type_complist) + { + return sema_expr_analyse_untyped_initializer(context, expr); + } // 3. Otherwise use the plain initializer. - if (assigned->type_kind == TYPE_ARRAY || assigned->type_kind == TYPE_INFERRED_ARRAY) + if (assigned->type_kind == TYPE_UNTYPED_LIST || assigned->type_kind == TYPE_ARRAY || assigned->type_kind == TYPE_INFERRED_ARRAY || assigned->type_kind == TYPE_SUBARRAY) { return sema_expr_analyse_array_plain_initializer(context, assigned, expr); } @@ -3235,6 +3198,10 @@ static inline bool sema_expr_analyse_initializer(Context *context, Type *externa static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to, Expr *expr) { + if (!to) + { + return sema_expr_analyse_initializer(context, type_complist, type_complist, expr); + } assert(to); Type *assigned = type_flatten(to); switch (assigned->type_kind) @@ -3243,6 +3210,7 @@ static inline bool sema_expr_analyse_initializer_list(Context *context, Type *to case TYPE_UNION: case TYPE_ARRAY: case TYPE_INFERRED_ARRAY: + case TYPE_SUBARRAY: return sema_expr_analyse_initializer(context, to, assigned, expr); default: break; @@ -4672,52 +4640,21 @@ static bool sema_expr_analyse_bit_not(Context *context, Type *to, Expr *expr, Ex static bool sema_expr_analyse_not(Expr *expr, Expr *inner) { - if (!type_may_convert_to_boolean(inner->type)) + if (!cast_may_implicit(inner->type, type_bool)) { - SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean valure.", type_quoted_error_string(inner->type)); + SEMA_ERROR(expr, "The use of '!' on %s is not allowed as it can't be converted to a boolean value.", type_quoted_error_string(inner->type)); return false; } + if (!cast_implicit(inner, type_bool)) return false; expr_copy_properties(expr, inner); expr_set_type(expr, type_bool); if (inner->expr_kind == EXPR_CONST) { + assert(inner->const_expr.const_kind == CONST_BOOL); expr->const_expr.const_kind = CONST_BOOL; expr->expr_kind = EXPR_CONST; - switch (inner->const_expr.const_kind) - { - case CONST_INTEGER: - expr->const_expr.b = bigint_cmp_zero(&inner->const_expr.i) == CMP_EQ; - return true; - case CONST_BOOL: - expr->const_expr.b = !inner->const_expr.b; - return true; - case CONST_FLOAT: - expr->const_expr.b = inner->const_expr.f == 0.0; - return true; - case CONST_STRING: - expr->const_expr.b = !inner->const_expr.string.len; - return true; - case CONST_BYTES: - expr->const_expr.b = !inner->const_expr.bytes.len; - return true; - case CONST_POINTER: - expr->const_expr.b = true; - return true; - case CONST_ERR: - expr->const_expr.b = inner->const_expr.err_val == NULL; - return true; - case CONST_ENUM: - { - Expr *value = inner->const_expr.enum_val->enum_constant.expr; - assert(value->expr_kind == EXPR_CONST && value->const_expr.const_kind == CONST_INTEGER); - expr->const_expr.b = bigint_cmp_zero(&value->const_expr.i) == CMP_EQ; - return true; - } - case CONST_TYPEID: - UNREACHABLE - } - UNREACHABLE + expr->const_expr.b = !inner->const_expr.b; } return true; } @@ -4907,7 +4844,7 @@ static inline bool sema_expr_analyse_unary(Context *context, Type *to, Expr *exp if (!sema_analyse_expr(context, to, inner)) return false; return sema_expr_analyse_bit_not(context, to, expr, inner); case UNARYOP_NOT: - if (!sema_analyse_expr(context, NULL, inner)) return false; + if (!sema_analyse_expr(context, type_bool, inner)) return false; return sema_expr_analyse_not(expr, inner); case UNARYOP_DEC: case UNARYOP_INC: @@ -6146,6 +6083,7 @@ static inline bool sema_analyse_expr_dispatch(Context *context, Type *to, Expr * case EXPR_ACCESS: return sema_expr_analyse_access(context, expr); case EXPR_INITIALIZER_LIST: + case EXPR_DESIGNATED_INITIALIZER_LIST: return sema_expr_analyse_initializer_list(context, to, expr); case EXPR_CAST: return sema_expr_analyse_cast(context, to, expr); @@ -6245,24 +6183,62 @@ bool sema_analyse_expr_value(Context *context, Type *to, Expr *expr) ArrayIndex sema_get_initializer_const_array_size(Context *context, Expr *initializer, bool *may_be_array, bool *is_const_size) { - assert(initializer->expr_kind == EXPR_INITIALIZER_LIST); - Expr **initializers = initializer->initializer_expr.initializer_expr; - *may_be_array = true; - *is_const_size = true; - unsigned element_count = vec_size(initializers); - // If it's empty or the first element is not a designator, we assume an array list - // with that many elements. - if (!element_count || initializers[0]->expr_kind != EXPR_DESIGNATOR) return element_count; + if (initializer->expr_kind == EXPR_CONST) + { + assert(initializer->const_expr.const_kind == CONST_LIST); + ConstInitializer *init = initializer->const_expr.list; + Type *type = type_lowering(initializer->type); + *is_const_size = true; + switch (init->kind) + { + case CONST_INIT_ZERO: + if (type->type_kind == TYPE_ARRAY) + { + *may_be_array = true; + return type->array.len; + } + if (type->type_kind == TYPE_SUBARRAY) + { + *may_be_array = true; + return 0; + } + *may_be_array = false; + return 0; + case CONST_INIT_ARRAY: + *may_be_array = true; + return VECLAST(init->init_array.elements)->init_array_value.index + 1; + case CONST_INIT_ARRAY_FULL: + *may_be_array = true; + return vec_size(init->init_array_full); + case CONST_INIT_ARRAY_VALUE: + UNREACHABLE; + case CONST_INIT_STRUCT: + case CONST_INIT_UNION: + case CONST_INIT_VALUE: + *may_be_array = false; + return 0; + } + UNREACHABLE + } + switch (initializer->expr_kind) + { + case EXPR_INITIALIZER_LIST: + *may_be_array = true; + *is_const_size = true; + return vec_size(initializer->initializer_list); + case EXPR_DESIGNATED_INITIALIZER_LIST: + break; + default: + UNREACHABLE + } + Expr **initializers = initializer->designated_init_list; ArrayIndex size = 0; // Otherwise we assume everything's a designator. VECEACH(initializers, i) { Expr *sub_initializer = initializers[i]; - if (sub_initializer->expr_kind != EXPR_DESIGNATOR) - { - // Simply messed up: a mix of designators and regular ones. - return -1; - } + assert(sub_initializer->expr_kind == EXPR_DESIGNATOR); + DesignatorElement *element = sub_initializer->designator_expr.path[0]; switch (element->kind) { diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index d5805957b..fdfd7753d 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1141,7 +1141,7 @@ static inline bool sema_analyse_foreach_stmt(Context *context, Ast *statement) Type *inferred_type = NULL; // We may have an initializer list, in this case we rely on an inferred type. - if (enumerator->expr_kind == EXPR_INITIALIZER_LIST) + if (expr_is_init_list(enumerator) || (enumerator->expr_kind == EXPR_CONST && enumerator->const_expr.const_kind == CONST_LIST)) { bool may_be_array; bool is_const_size; diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index 0349b417b..a1572005c 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -155,6 +155,8 @@ bool sema_resolve_type(Context *context, Type *type) case TYPE_ANYERR: case TYPE_STRLIT: case TYPE_VECTOR: + case TYPE_TYPEINFO: + case TYPE_UNTYPED_LIST: return true; case TYPE_POINTER: return sema_resolve_type(context, type->pointer); @@ -170,8 +172,6 @@ bool sema_resolve_type(Context *context, Type *type) case TYPE_SUBARRAY: case TYPE_INFERRED_ARRAY: return sema_resolve_type(context, type->array.base); - case TYPE_TYPEINFO: - TODO case TYPE_VIRTUAL: TODO; } diff --git a/src/compiler/types.c b/src/compiler/types.c index f9b9d8eb2..2e93827d5 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -11,8 +11,8 @@ static struct Type u8, u16, u32, u64, u128; Type f16, f32, f64, f128, fxx; Type usz, isz, uptr, iptr, uptrdiff, iptrdiff; - Type voidstar, typeid, anyerr, typeinfo; - Type str, varheader, virtual, virtual_generic; + Type voidstar, typeid, anyerr, typeinfo, ctlist; + Type str, virtual, virtual_generic; } t; Type *type_bool = &t.u1; @@ -46,7 +46,7 @@ Type *type_compint = &t.ixx; Type *type_compfloat = &t.fxx; Type *type_compstr = &t.str; Type *type_anyerr = &t.anyerr; -Type *type_varheader = &t.varheader; +Type *type_complist = &t.ctlist; static unsigned size_subarray; static AlignSize alignment_subarray; @@ -126,6 +126,7 @@ const char *type_to_error_string(Type *type) case TYPE_VIRTUAL_ANY: case TYPE_VIRTUAL: case TYPE_ANYERR: + case TYPE_UNTYPED_LIST: return type->name; case TYPE_FUNC: return strcat_arena("func ", type->func.mangled_function_signature); @@ -202,9 +203,7 @@ ByteSize type_size(Type *type) } return width; } - case TYPE_POISONED: - case TYPE_TYPEINFO: - case TYPE_INFERRED_ARRAY: + case CT_TYPES: UNREACHABLE; case TYPE_TYPEDEF: return type_size(type->canonical); @@ -365,6 +364,7 @@ bool type_is_abi_aggregate(Type *type) return true; case TYPE_TYPEINFO: case TYPE_INFERRED_ARRAY: + case TYPE_UNTYPED_LIST: UNREACHABLE } UNREACHABLE @@ -502,15 +502,13 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements) type = type->decl->bitstruct.base_type->type; goto RETRY; case TYPE_FXX: - case TYPE_POISONED: case TYPE_IXX: case TYPE_VOID: - case TYPE_TYPEINFO: case TYPE_TYPEID: case TYPE_FUNC: case TYPE_STRLIT: case TYPE_SUBARRAY: - case TYPE_INFERRED_ARRAY: + case CT_TYPES: return false; case TYPE_VIRTUAL: case TYPE_VIRTUAL_ANY: @@ -705,6 +703,7 @@ AlignSize type_abi_alignment(Type *type) { case TYPE_POISONED: case TYPE_TYPEINFO: + case TYPE_UNTYPED_LIST: UNREACHABLE; case TYPE_BITSTRUCT: return type_abi_alignment(type->decl->bitstruct.base_type->type); @@ -992,7 +991,6 @@ Type *type_get_indexed_type(Type *type) } } - static Type *type_create_array(Type *element_type, uint64_t len, bool vector, bool canonical) { if (canonical) element_type = element_type->canonical; @@ -1146,6 +1144,7 @@ static void type_append_name_to_scratch(Type *type) case TYPE_IXX: case TYPE_FXX: case TYPE_STRLIT: + case TYPE_UNTYPED_LIST: case TYPE_INFERRED_ARRAY: case TYPE_TYPEINFO: UNREACHABLE @@ -1240,6 +1239,7 @@ void type_setup(PlatformTarget *target) type_create("typeinfo", &t.typeinfo, TYPE_TYPEINFO, 1, 1, 1); + type_create("complist", &t.ctlist, TYPE_UNTYPED_LIST, 1, 1, 1); type_init("typeid", &t.typeid, TYPE_TYPEID, target->width_pointer, target->align_pointer); type_init("void*", &t.voidstar, TYPE_POINTER, target->width_pointer, target->align_pointer); @@ -1409,6 +1409,7 @@ bool type_may_convert_to_boolean(Type *type) case TYPE_ANYERR: case TYPE_ERRTYPE: case TYPE_STRLIT: + case TYPE_UNTYPED_LIST: return true; case TYPE_FUNC: case TYPE_ARRAY: @@ -1596,6 +1597,7 @@ Type *type_find_max_type(Type *type, Type *other) case TYPE_ANYERR: case TYPE_TYPEID: case TYPE_STRUCT: + case TYPE_UNTYPED_LIST: TODO case TYPE_TYPEDEF: UNREACHABLE diff --git a/test/test_suite/initializer_lists/general_tests.c3t b/test/test_suite/initializer_lists/general_tests.c3t new file mode 100644 index 000000000..5a5f69cd0 --- /dev/null +++ b/test/test_suite/initializer_lists/general_tests.c3t @@ -0,0 +1,27 @@ +// #skip + +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} + +func int test() +{ + Baz ffe = { .x = 1 }; + int[1] azz = {}; + int[*] a = {}; + var $foo = { 1, 2, 3 }; + bool x = ! int[] { 1, 2, 3 }; + Bar b = {}; + Baz z = {}; + int[] sub = {}; + Bar[] foo = {}; + Baz[3] baz = {}; + return 1; +} \ No newline at end of file diff --git a/test/test_suite/initializer_lists/zero_init.c3t b/test/test_suite/initializer_lists/zero_init.c3t new file mode 100644 index 000000000..0d9747bb3 --- /dev/null +++ b/test/test_suite/initializer_lists/zero_init.c3t @@ -0,0 +1,51 @@ +// #target: x64-darwin + +union Baz +{ + int x; + double y; +} +struct Bar +{ + int x; + int y; +} +func int test() +{ + int[1] azz = {}; + int[*] a = {}; + Bar b = {}; + Baz z = {}; + int[] sub = {}; + Bar[] foo = {}; + Baz[3] baz = {}; + return 1; +} + +// #expect: zero_init.ll + +define i32 @zero_init.test() #0 { +entry: + %azz = alloca [1 x i32], align 4 + %a = alloca [0 x i32], align 4 + %b = alloca %Bar, align 4 + %z = alloca %Baz, align 8 + %sub = alloca %"int[]", align 8 + %foo = alloca %"Bar[]", align 8 + %baz = alloca [3 x %Baz], align 16 + %0 = bitcast [1 x i32]* %azz to i8* + call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 4, i1 false) + %1 = bitcast [0 x i32]* %a to i8* + call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 0, i1 false) + %2 = bitcast %Bar* %b to i8* + call void @llvm.memset.p0i8.i64(i8* align 4 %2, i8 0, i64 8, i1 false) + %3 = bitcast %Baz* %z to i8* + call void @llvm.memset.p0i8.i64(i8* align 8 %3, i8 0, i64 8, i1 false) + %4 = bitcast %"int[]"* %sub to i8* + call void @llvm.memset.p0i8.i64(i8* align 8 %4, i8 0, i64 16, i1 false) + %5 = bitcast %"Bar[]"* %foo to i8* + call void @llvm.memset.p0i8.i64(i8* align 8 %5, i8 0, i64 16, i1 false) + %6 = bitcast [3 x %Baz]* %baz to i8* + call void @llvm.memset.p0i8.i64(i8* align 16 %6, i8 0, i64 24, i1 false) + ret i32 1 +} \ No newline at end of file diff --git a/test/test_suite/statements/foreach_errors.c3 b/test/test_suite/statements/foreach_errors.c3 index c12396034..c3afb1db8 100644 --- a/test/test_suite/statements/foreach_errors.c3 +++ b/test/test_suite/statements/foreach_errors.c3 @@ -52,8 +52,3 @@ func void test8() foreach (int a : { z }) foo(); // #error: 'int[3]' into 'int' } -func void test9() -{ - foreach (int a : { [2] = 1 }) foo(); - foreach (int a : { [2] = 2, 1 }) foo(); // #error: The initializer mixes designated initialization with array initialization -} \ No newline at end of file diff --git a/test/test_suite/statements/foreach_parse_error.c3 b/test/test_suite/statements/foreach_parse_error.c3 new file mode 100644 index 000000000..38d1e0ceb --- /dev/null +++ b/test/test_suite/statements/foreach_parse_error.c3 @@ -0,0 +1,5 @@ +func void test9() +{ + foreach (int a : { [2] = 1 }) foo(); + foreach (int a : { [2] = 2, 1 }) foo(); // #error: Normal initialization cannot be mixed with designated initialization. +} \ No newline at end of file