authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-04 23:37:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-04 23:37:17-07:00
loga11d0aaf62e3ebf2f46307d1546b8105792c8dd0
tree3dc29343eb5eefa115047b49bf1be23f484aa12c
parent3c551628268e88c6d6dcbe729e1bc756a689dbda

progress toward compile time constant expression evaluation


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}
235235
236static 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
236static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) {260static 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 }
276300
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};
17001704
1701static void define_builtin_types(CodeGen *g) {1705static 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) {
2793uint64_t num_lit_bit_count(NumLit num_lit) {2809uint64_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,
312316
313 NumLitCount317 NumLitCount
314};318};
...@@ -322,6 +326,7 @@ struct AstNodeNumberLiteral {...@@ -322,6 +326,7 @@ struct AstNodeNumberLiteral {
322326
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(
782use "std.zig";
783
784const ARRAY_SIZE : u8 = 20;
785
786pub 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}
781794
782////////////////////////////////////////////////////////////////////////////////////795////////////////////////////////////////////////////////////////////////////////////