| 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 | 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 | 260 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) { |
| 237 | 261 | assert(node->type == NodeTypeType); |
| 238 | 262 | alloc_codegen_node(node); |
| ... | ... | @@ -275,14 +299,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry |
| 275 | 299 | } |
| 276 | 300 | |
| 277 | 301 | AstNode *size_node = node->data.type.array_size; |
| 278 | if (size_node->type == NodeTypeNumberLiteral && | |
| 279 | is_num_lit_unsigned(size_node->data.number_literal.kind)) | |
| 280 | { | |
| 281 | type_node->entry = get_array_type(g, import, child_type, | |
| 282 | size_node->data.number_literal.data.x_uint); | |
| 302 | TypeTableEntry *size_type = analyze_expression(g, import, context, | |
| 303 | g->builtin_types.entry_usize, size_node); | |
| 304 | if (size_type->id == TypeTableEntryIdInvalid) { | |
| 305 | type_node->entry = g->builtin_types.entry_invalid; | |
| 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 | 320 | } else { |
| 284 | 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 | 323 | type_node->entry = g->builtin_types.entry_invalid; |
| 287 | 324 | } |
| 288 | 325 | return type_node->entry; |
src/codegen.cpp+4| ... | ... | @@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = { |
| 1696 | 1696 | NumLitU16, |
| 1697 | 1697 | NumLitU32, |
| 1698 | 1698 | NumLitU64, |
| 1699 | NumLitI8, | |
| 1700 | NumLitI16, | |
| 1701 | NumLitI32, | |
| 1702 | NumLitI64, | |
| 1699 | 1703 | }; |
| 1700 | 1704 | |
| 1701 | 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 | 2750 | return "u32"; |
| 2751 | 2751 | case NumLitU64: |
| 2752 | 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 | 2761 | case NumLitCount: |
| 2754 | 2762 | zig_unreachable(); |
| 2755 | 2763 | } |
| ... | ... | @@ -2761,6 +2769,10 @@ bool is_num_lit_unsigned(NumLit num_lit) { |
| 2761 | 2769 | case NumLitF32: |
| 2762 | 2770 | case NumLitF64: |
| 2763 | 2771 | case NumLitF128: |
| 2772 | case NumLitI8: | |
| 2773 | case NumLitI16: | |
| 2774 | case NumLitI32: | |
| 2775 | case NumLitI64: | |
| 2764 | 2776 | return false; |
| 2765 | 2777 | case NumLitU8: |
| 2766 | 2778 | case NumLitU16: |
| ... | ... | @@ -2783,6 +2795,10 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2783 | 2795 | case NumLitU16: |
| 2784 | 2796 | case NumLitU32: |
| 2785 | 2797 | case NumLitU64: |
| 2798 | case NumLitI8: | |
| 2799 | case NumLitI16: | |
| 2800 | case NumLitI32: | |
| 2801 | case NumLitI64: | |
| 2786 | 2802 | return false; |
| 2787 | 2803 | case NumLitCount: |
| 2788 | 2804 | zig_unreachable(); |
| ... | ... | @@ -2793,13 +2809,17 @@ bool is_num_lit_float(NumLit num_lit) { |
| 2793 | 2809 | uint64_t num_lit_bit_count(NumLit num_lit) { |
| 2794 | 2810 | switch (num_lit) { |
| 2795 | 2811 | case NumLitU8: |
| 2812 | case NumLitI8: | |
| 2796 | 2813 | return 8; |
| 2797 | 2814 | case NumLitU16: |
| 2815 | case NumLitI16: | |
| 2798 | 2816 | return 16; |
| 2799 | 2817 | case NumLitU32: |
| 2818 | case NumLitI32: | |
| 2800 | 2819 | case NumLitF32: |
| 2801 | 2820 | return 32; |
| 2802 | 2821 | case NumLitU64: |
| 2822 | case NumLitI64: | |
| 2803 | 2823 | case NumLitF64: |
| 2804 | 2824 | return 64; |
| 2805 | 2825 | case NumLitF128: |
src/parser.hpp+5| ... | ... | @@ -309,6 +309,10 @@ enum NumLit { |
| 309 | 309 | NumLitU16, |
| 310 | 310 | NumLitU32, |
| 311 | 311 | NumLitU64, |
| 312 | NumLitI8, | |
| 313 | NumLitI16, | |
| 314 | NumLitI32, | |
| 315 | NumLitI64, | |
| 312 | 316 | |
| 313 | 317 | NumLitCount |
| 314 | 318 | }; |
| ... | ... | @@ -322,6 +326,7 @@ struct AstNodeNumberLiteral { |
| 322 | 326 | |
| 323 | 327 | union { |
| 324 | 328 | uint64_t x_uint; |
| 329 | int64_t x_int; | |
| 325 | 330 | double x_float; |
| 326 | 331 | } data; |
| 327 | 332 | }; |
test/run_tests.cpp+13| ... | ... | @@ -777,6 +777,19 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 777 | 777 | return 0; |
| 778 | 778 | } |
| 779 | 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 | //////////////////////////////////////////////////////////////////////////////////// |