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,
233233 }
234234}
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
236260static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) {
237261 assert(node->type == NodeTypeType);
238262 alloc_codegen_node(node);
......@@ -275,14 +299,27 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry
275299 }
276300
277301 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 }
283320 } else {
284321 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"));
286323 type_node->entry = g->builtin_types.entry_invalid;
287324 }
288325 return type_node->entry;
src/codegen.cpp+4
......@@ -1696,6 +1696,10 @@ static const NumLit num_lit_kinds[] = {
16961696 NumLitU16,
16971697 NumLitU32,
16981698 NumLitU64,
1699 NumLitI8,
1700 NumLitI16,
1701 NumLitI32,
1702 NumLitI64,
16991703};
17001704
17011705static void define_builtin_types(CodeGen *g) {
src/parser.cpp+20
......@@ -2750,6 +2750,14 @@ const char *num_lit_str(NumLit num_lit) {
27502750 return "u32";
27512751 case NumLitU64:
27522752 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";
27532761 case NumLitCount:
27542762 zig_unreachable();
27552763 }
......@@ -2761,6 +2769,10 @@ bool is_num_lit_unsigned(NumLit num_lit) {
27612769 case NumLitF32:
27622770 case NumLitF64:
27632771 case NumLitF128:
2772 case NumLitI8:
2773 case NumLitI16:
2774 case NumLitI32:
2775 case NumLitI64:
27642776 return false;
27652777 case NumLitU8:
27662778 case NumLitU16:
......@@ -2783,6 +2795,10 @@ bool is_num_lit_float(NumLit num_lit) {
27832795 case NumLitU16:
27842796 case NumLitU32:
27852797 case NumLitU64:
2798 case NumLitI8:
2799 case NumLitI16:
2800 case NumLitI32:
2801 case NumLitI64:
27862802 return false;
27872803 case NumLitCount:
27882804 zig_unreachable();
......@@ -2793,13 +2809,17 @@ bool is_num_lit_float(NumLit num_lit) {
27932809uint64_t num_lit_bit_count(NumLit num_lit) {
27942810 switch (num_lit) {
27952811 case NumLitU8:
2812 case NumLitI8:
27962813 return 8;
27972814 case NumLitU16:
2815 case NumLitI16:
27982816 return 16;
27992817 case NumLitU32:
2818 case NumLitI32:
28002819 case NumLitF32:
28012820 return 32;
28022821 case NumLitU64:
2822 case NumLitI64:
28032823 case NumLitF64:
28042824 return 64;
28052825 case NumLitF128:
src/parser.hpp+5
......@@ -309,6 +309,10 @@ enum NumLit {
309309 NumLitU16,
310310 NumLitU32,
311311 NumLitU64,
312 NumLitI8,
313 NumLitI16,
314 NumLitI32,
315 NumLitI64,
312316
313317 NumLitCount
314318};
......@@ -322,6 +326,7 @@ struct AstNodeNumberLiteral {
322326
323327 union {
324328 uint64_t x_uint;
329 int64_t x_int;
325330 double x_float;
326331 } data;
327332};
test/run_tests.cpp+13
......@@ -777,6 +777,19 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
777777 return 0;
778778}
779779 )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");
780793}
781794
782795////////////////////////////////////////////////////////////////////////////////////