diff --git a/src/all_types.hpp b/src/all_types.hpp index 45669ed43..21da03af0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -135,6 +135,7 @@ enum NodeType { NodeTypeUse, NodeTypeBoolLiteral, NodeTypeNullLiteral, + NodeTypeUndefinedLiteral, NodeTypeIfBoolExpr, NodeTypeIfVarExpr, NodeTypeWhileExpr, @@ -609,6 +610,12 @@ struct AstNodeNullLiteral { Expr resolved_expr; }; +struct AstNodeUndefinedLiteral { + // populated by semantic analyzer + StructValExprCodeGen resolved_struct_val_expr; + Expr resolved_expr; +}; + struct AstNodeSymbolExpr { Buf symbol; @@ -692,6 +699,7 @@ struct AstNode { AstNodeContainerInitExpr container_init_expr; AstNodeStructValueField struct_val_field; AstNodeNullLiteral null_literal; + AstNodeUndefinedLiteral undefined_literal; AstNodeSymbolExpr symbol_expr; AstNodeBoolLiteral bool_literal; AstNodeBreakExpr break_expr; diff --git a/src/analyze.cpp b/src/analyze.cpp index cc061a6b8..29cd794b5 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -55,6 +55,7 @@ static AstNode *first_executing_node(AstNode *node) { case NodeTypeUse: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeIfBoolExpr: case NodeTypeIfVarExpr: case NodeTypeLabel: @@ -1006,6 +1007,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode case NodeTypeCharLiteral: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypeIfBoolExpr: @@ -1079,7 +1081,9 @@ static bool type_has_codegen_value(TypeTableEntryId id) { } static void add_global_const_expr(CodeGen *g, Expr *expr) { - if (expr->const_val.ok && type_has_codegen_value(expr->type_entry->id) && !expr->has_global_const) { + if (expr->const_val.ok && + type_has_codegen_value(expr->type_entry->id) && !expr->has_global_const) + { g->global_const_list.append(expr); expr->has_global_const = true; } @@ -2470,6 +2474,20 @@ static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *i return resolve_expr_const_val_as_null(g, node, expected_type); } +static TypeTableEntry *analyze_undefined_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, + TypeTableEntry *expected_type, AstNode *node) +{ + Expr *expr = get_resolved_expr(node); + ConstExprValue *const_val = &expr->const_val; + + const_val->ok = true; + + zig_panic("TODO"); + + return expected_type; +} + + static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry *import, BlockContext *block_context, TypeTableEntry *expected_type, AstNode *node) { @@ -3634,11 +3652,12 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, case NodeTypeBoolLiteral: return_type = resolve_expr_const_val_as_bool(g, node, node->data.bool_literal.value); break; - case NodeTypeNullLiteral: return_type = analyze_null_literal_expr(g, import, context, expected_type, node); break; - + case NodeTypeUndefinedLiteral: + return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node); + break; case NodeTypeSymbol: return_type = analyze_symbol_expr(g, import, context, expected_type, node); break; @@ -3804,6 +3823,7 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode case NodeTypeCharLiteral: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypeIfBoolExpr: @@ -3837,6 +3857,7 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode case NodeTypeCharLiteral: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeGoto: case NodeTypeBreak: case NodeTypeContinue: @@ -4155,6 +4176,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast case NodeTypeCharLiteral: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeSymbol: case NodeTypePrefixOpExpr: case NodeTypeIfBoolExpr: @@ -4364,6 +4386,8 @@ Expr *get_resolved_expr(AstNode *node) { return &node->data.bool_literal.resolved_expr; case NodeTypeNullLiteral: return &node->data.null_literal.resolved_expr; + case NodeTypeUndefinedLiteral: + return &node->data.undefined_literal.resolved_expr; case NodeTypeGoto: return &node->data.goto_expr.resolved_expr; case NodeTypeBreak: @@ -4438,6 +4462,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { case NodeTypeUse: case NodeTypeBoolLiteral: case NodeTypeNullLiteral: + case NodeTypeUndefinedLiteral: case NodeTypeLabel: case NodeTypeGoto: case NodeTypeBreak: diff --git a/src/codegen.cpp b/src/codegen.cpp index 6a5008b94..65b3b91a4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1486,22 +1486,6 @@ static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) { return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); } -static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) { - assert(node->type == NodeTypeNullLiteral); - - TypeTableEntry *type_entry = get_expr_type(node); - assert(type_entry->id == TypeTableEntryIdMaybe); - - LLVMValueRef tmp_struct_ptr = node->data.null_literal.resolved_struct_val_expr.ptr; - - add_debug_source_node(g, node); - LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, ""); - LLVMValueRef null_value = LLVMConstNull(LLVMInt1Type()); - LLVMBuildStore(g->builder, null_value, field_ptr); - - return tmp_struct_ptr; -} - static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeContainerInitExpr); @@ -1963,7 +1947,11 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { case NodeTypeFieldAccessExpr: return gen_field_access_expr(g, node, false); case NodeTypeNullLiteral: - return gen_null_literal(g, node); + // caught by constant expression eval codegen + zig_unreachable(); + case NodeTypeUndefinedLiteral: + // caught by constant expression eval codegen + zig_unreachable(); case NodeTypeIfBoolExpr: return gen_if_bool_expr(g, node); case NodeTypeIfVarExpr: diff --git a/src/parser.cpp b/src/parser.cpp index 90cabdad2..8370a022b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -129,6 +129,8 @@ const char *node_type_str(NodeType node_type) { return "BoolLiteral"; case NodeTypeNullLiteral: return "NullLiteral"; + case NodeTypeUndefinedLiteral: + return "UndefinedLiteral"; case NodeTypeIfBoolExpr: return "IfBoolExpr"; case NodeTypeIfVarExpr: @@ -412,6 +414,9 @@ void ast_print(AstNode *node, int indent) { case NodeTypeContinue: fprintf(stderr, "%s\n", node_type_str(node->type)); break; + case NodeTypeUndefinedLiteral: + fprintf(stderr, "%s\n", node_type_str(node->type)); + break; case NodeTypeAsmExpr: fprintf(stderr, "%s\n", node_type_str(node->type)); break; @@ -1368,7 +1373,7 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mand /* PrimaryExpression : "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | AsmExpression | ("%." "Symbol") -KeywordLiteral : token(True) | token(False) | token(Null) | token(Break) | token(Continue) +KeywordLiteral : "true" | "false" | "null" | "break" | "continue" | "undefined" */ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) { Token *token = &pc->tokens->at(*token_index); @@ -1410,6 +1415,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool AstNode *node = ast_create_node(pc, NodeTypeContinue, token); *token_index += 1; return node; + } else if (token->id == TokenIdKeywordUndefined) { + AstNode *node = ast_create_node(pc, NodeTypeUndefinedLiteral, token); + *token_index += 1; + return node; } else if (token->id == TokenIdAtSign) { *token_index += 1; Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); @@ -3202,6 +3211,9 @@ void normalize_parent_ptrs(AstNode *node) { case NodeTypeNullLiteral: // none break; + case NodeTypeUndefinedLiteral: + // none + break; case NodeTypeIfBoolExpr: set_field(&node->data.if_bool_expr.condition); set_field(&node->data.if_bool_expr.then_block);