| author | |
| committer | |
| log | a11d0aaf62e3ebf2f46307d1546b8105792c8dd0 |
| tree | 3dc29343eb5eefa115047b49bf1be23f484aa12c |
| parent | 3c551628268e88c6d6dcbe729e1bc756a689dbda |
5 files changed, 85 insertions(+), 6 deletions(-)
src/analyze.cpp+43-6| ... | @@ -233,6 +233,30 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, | ... | @@ -233,6 +233,30 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import, |
| 233 | } | 233 | } |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context, | ||
| 237 | AstNode *node, AstNodeNumberLiteral *out_number_literal) | ||
| 238 | { | ||
| 239 | switch (node->type) { | ||
| 240 | case NodeTypeNumberLiteral: | ||
| 241 | *out_number_literal = node->data.number_literal; | ||
| 242 | return node->codegen_node->expr_node.type_entry; | ||
| 243 | case NodeTypeBinOpExpr: | ||
| 244 | zig_panic("TODO eval_const_expr bin op expr"); | ||
| 245 | break; | ||
| 246 | case NodeTypeSymbol: | ||
| 247 | { | ||
| 248 | VariableTableEntry *var = find_variable(context, &node->data.symbol); | ||
| 249 | assert(var); | ||
| 250 | AstNode *decl_node = var->decl_node; | ||
| 251 | AstNode *expr_node = decl_node->data.variable_declaration.expr; | ||
| 252 | BlockContext *next_context = expr_node->codegen_node->expr_node.block_context; | ||
| 253 | return eval_const_expr(g, next_context, expr_node, out_number_literal); | ||
| 254 | } | ||
| 255 | default: | ||
| 256 | return g->builtin_types.entry_invalid; | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 236 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) { | 260 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) { |
| 237 | assert(node->type == NodeTypeType); | 261 | assert(node->type == NodeTypeType); |
| 238 | alloc_codegen_node(node); | 262 | alloc_codegen_node(node); |
| ... | @@ -275,14 +299,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry | ... | @@ -275,14 +299,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 275 | } | 299 | } |
| 276 | 300 | ||
| 277 | AstNode *size_node = node->data.type.array_size; | 301 | AstNode *size_node = node->data.type.array_size; |
| 278 | if (size_node->type == NodeTypeNumberLiteral && | 302 | TypeTableEntry *size_type = analyze_expression(g, import, context, |
| 279 | is_num_lit_unsigned(size_node->data.number_literal.kind)) | 303 | g->builtin_types.entry_usize, size_node); |
| 280 | { | 304 | if (size_type->id == TypeTableEntryIdInvalid) { |
| 281 | type_node->entry = get_array_type(g, import, child_type, | 305 | type_node->entry = g->builtin_types.entry_invalid; |
| 282 | size_node->data.number_literal.data.x_uint); | 306 | return type_node->entry; |
| 307 | } | ||
| 308 | |||
| 309 | AstNodeNumberLiteral number_literal; | ||
| 310 | TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal); | ||
| 311 | |||
| 312 | if (resolved_type->id == TypeTableEntryIdInt) { | ||
| 313 | if (resolved_type->data.integral.is_signed) { | ||
| 314 | add_node_error(g, size_node, | ||
| 315 | buf_create_from_str("array size must be unsigned integer")); | ||
| 316 | type_node->entry = g->builtin_types.entry_invalid; | ||
| 317 | } else { | ||
| 318 | type_node->entry = get_array_type(g, import, child_type, number_literal.data.x_uint); | ||
| 319 | } | ||
| 283 | } else { | 320 | } else { |
| 284 | add_node_error(g, size_node, | 321 | add_node_error(g, size_node, |
| 285 | buf_create_from_str("array size must be literal unsigned integer")); | 322 | buf_create_from_str("unable to resolve constant expression")); |
| 286 | type_node->entry = g->builtin_types.entry_invalid; | 323 | type_node->entry = g->builtin_types.entry_invalid; |
| 287 | } | 324 | } |
| 288 | return type_node->entry; | 325 | return type_node->entry; |
src/codegen.cpp+4| ... | @@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = { | ... | @@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = { |
| 1696 | NumLitU16, | 1696 | NumLitU16, |
| 1697 | NumLitU32, | 1697 | NumLitU32, |
| 1698 | NumLitU64, | 1698 | NumLitU64, |
| 1699 | NumLitI8, | ||
| 1700 | NumLitI16, | ||
| 1701 | NumLitI32, | ||
| 1702 | NumLitI64, | ||
| 1699 | }; | 1703 | }; |
| 1700 | 1704 | ||
| 1701 | static void define_builtin_types(CodeGen *g) { | 1705 | static void define_builtin_types(CodeGen *g) { |
src/parser.cpp+20| ... | @@ -2750,6 +2750,14 @@ const char *num_lit_str(NumLit num_lit) { | ... | @@ -2750,6 +2750,14 @@ const char *num_lit_str(NumLit num_lit) { |
| 2750 | return "u32"; | 2750 | return "u32"; |
| 2751 | case NumLitU64: | 2751 | case NumLitU64: |
| 2752 | return "u64"; | 2752 | return "u64"; |
| 2753 | case NumLitI8: | ||
| 2754 | return "i8"; | ||
| 2755 | case NumLitI16: | ||
| 2756 | return "i16"; | ||
| 2757 | case NumLitI32: | ||
| 2758 | return "i32"; | ||
| 2759 | case NumLitI64: | ||
| 2760 | return "i64"; | ||
| 2753 | case NumLitCount: | 2761 | case NumLitCount: |
| 2754 | zig_unreachable(); | 2762 | zig_unreachable(); |
| 2755 | } | 2763 | } |
| ... | @@ -2761,6 +2769,10 @@ bool is_num_lit_unsigned(NumLit num_lit) { | ... | @@ -2761,6 +2769,10 @@ bool is_num_lit_unsigned(NumLit num_lit) { |
| 2761 | case NumLitF32: | 2769 | case NumLitF32: |
| 2762 | case NumLitF64: | 2770 | case NumLitF64: |
| 2763 | case NumLitF128: | 2771 | case NumLitF128: |
| 2772 | case NumLitI8: | ||
| 2773 | case NumLitI16: | ||
| 2774 | case NumLitI32: | ||
| 2775 | case NumLitI64: | ||
| 2764 | return false; | 2776 | return false; |
| 2765 | case NumLitU8: | 2777 | case NumLitU8: |
| 2766 | case NumLitU16: | 2778 | case NumLitU16: |
| ... | @@ -2783,6 +2795,10 @@ bool is_num_lit_float(NumLit num_lit) { | ... | @@ -2783,6 +2795,10 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2783 | case NumLitU16: | 2795 | case NumLitU16: |
| 2784 | case NumLitU32: | 2796 | case NumLitU32: |
| 2785 | case NumLitU64: | 2797 | case NumLitU64: |
| 2798 | case NumLitI8: | ||
| 2799 | case NumLitI16: | ||
| 2800 | case NumLitI32: | ||
| 2801 | case NumLitI64: | ||
| 2786 | return false; | 2802 | return false; |
| 2787 | case NumLitCount: | 2803 | case NumLitCount: |
| 2788 | zig_unreachable(); | 2804 | zig_unreachable(); |
| ... | @@ -2793,13 +2809,17 @@ bool is_num_lit_float(NumLit num_lit) { | ... | @@ -2793,13 +2809,17 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2793 | uint64_t num_lit_bit_count(NumLit num_lit) { | 2809 | uint64_t num_lit_bit_count(NumLit num_lit) { |
| 2794 | switch (num_lit) { | 2810 | switch (num_lit) { |
| 2795 | case NumLitU8: | 2811 | case NumLitU8: |
| 2812 | case NumLitI8: | ||
| 2796 | return 8; | 2813 | return 8; |
| 2797 | case NumLitU16: | 2814 | case NumLitU16: |
| 2815 | case NumLitI16: | ||
| 2798 | return 16; | 2816 | return 16; |
| 2799 | case NumLitU32: | 2817 | case NumLitU32: |
| 2818 | case NumLitI32: | ||
| 2800 | case NumLitF32: | 2819 | case NumLitF32: |
| 2801 | return 32; | 2820 | return 32; |
| 2802 | case NumLitU64: | 2821 | case NumLitU64: |
| 2822 | case NumLitI64: | ||
| 2803 | case NumLitF64: | 2823 | case NumLitF64: |
| 2804 | return 64; | 2824 | return 64; |
| 2805 | case NumLitF128: | 2825 | case NumLitF128: |
src/parser.hpp+5| ... | @@ -309,6 +309,10 @@ enum NumLit { | ... | @@ -309,6 +309,10 @@ enum NumLit { |
| 309 | NumLitU16, | 309 | NumLitU16, |
| 310 | NumLitU32, | 310 | NumLitU32, |
| 311 | NumLitU64, | 311 | NumLitU64, |
| 312 | NumLitI8, | ||
| 313 | NumLitI16, | ||
| 314 | NumLitI32, | ||
| 315 | NumLitI64, | ||
| 312 | 316 | ||
| 313 | NumLitCount | 317 | NumLitCount |
| 314 | }; | 318 | }; |
| ... | @@ -322,6 +326,7 @@ struct AstNodeNumberLiteral { | ... | @@ -322,6 +326,7 @@ struct AstNodeNumberLiteral { |
| 322 | 326 | ||
| 323 | union { | 327 | union { |
| 324 | uint64_t x_uint; | 328 | uint64_t x_uint; |
| 329 | int64_t x_int; | ||
| 325 | double x_float; | 330 | double x_float; |
| 326 | } data; | 331 | } data; |
| 327 | }; | 332 | }; |
test/run_tests.cpp+13| ... | @@ -777,6 +777,19 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | ... | @@ -777,6 +777,19 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 777 | return 0; | 777 | return 0; |
| 778 | } | 778 | } |
| 779 | )SOURCE", "OK\n"); | 779 | )SOURCE", "OK\n"); |
| 780 | |||
| 781 | add_simple_case("constant expressions", R"SOURCE( | ||
| 782 | use "std.zig"; | ||
| 783 | |||
| 784 | const ARRAY_SIZE : u8 = 20; | ||
| 785 | |||
| 786 | pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | ||
| 787 | var array : [u8; ARRAY_SIZE]; | ||
| 788 | print_u64(#sizeof(#typeof(array))); | ||
| 789 | print_str("\n"); | ||
| 790 | return 0; | ||
| 791 | } | ||
| 792 | )SOURCE", "20\n"); | ||
| 780 | } | 793 | } |
| 781 | 794 | ||
| 782 | //////////////////////////////////////////////////////////////////////////////////// | 795 | //////////////////////////////////////////////////////////////////////////////////// |