authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-26 22:33:33-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-26 22:33:33-04:00
log87b7c28c9aa618eda5589693ee79a5737d907bac
treee152ba0b645aaac3f541973781b5c5c5baae111c
parent7ce7e2c9d1d43886c93f34b67d32ef77cc0d8a6e

cstr.len and cstr.cmp can run at compile time

closes #140

3 files changed, 167 insertions(+), 104 deletions(-)

src/all_types.hpp-27
...@@ -1111,33 +1111,6 @@ struct FnTableEntry {...@@ -1111,33 +1111,6 @@ struct FnTableEntry {
1111 ZigList<AstNode *> goto_list;1111 ZigList<AstNode *> goto_list;
1112};1112};
11131113
1114struct EvalVar {
1115 Buf *name;
1116 ConstExprValue value;
1117};
1118
1119struct EvalScope {
1120 BlockContext *block_context;
1121 ZigList<EvalVar> vars;
1122};
1123
1124struct EvalFnRoot {
1125 CodeGen *codegen;
1126 FnTableEntry *fn;
1127 AstNode *call_node;
1128 size_t branch_quota;
1129 size_t branches_used;
1130 AstNode *exceeded_quota_node;
1131 bool abort;
1132};
1133
1134struct EvalFn {
1135 EvalFnRoot *root;
1136 FnTableEntry *fn;
1137 ConstExprValue *return_expr;
1138 ZigList<EvalScope*> scope_stack;
1139};
1140
1141enum BuiltinFnId {1114enum BuiltinFnId {
1142 BuiltinFnIdInvalid,1115 BuiltinFnIdInvalid,
1143 BuiltinFnIdMemcpy,1116 BuiltinFnIdMemcpy,
src/eval.cpp+149-69
...@@ -2,6 +2,34 @@...@@ -2,6 +2,34 @@
2#include "analyze.hpp"2#include "analyze.hpp"
3#include "error.hpp"3#include "error.hpp"
44
5struct EvalVar {
6 Buf *name;
7 ConstExprValue value;
8};
9
10struct EvalScope {
11 BlockContext *block_context;
12 ZigList<EvalVar> vars;
13};
14
15struct EvalFnRoot {
16 CodeGen *codegen;
17 FnTableEntry *fn;
18 AstNode *call_node;
19 size_t branch_quota;
20 size_t branches_used;
21 AstNode *exceeded_quota_node;
22 bool abort;
23};
24
25struct EvalFn {
26 EvalFnRoot *root;
27 FnTableEntry *fn;
28 ConstExprValue *return_expr;
29 ZigList<EvalScope*> scope_stack;
30};
31
32
5static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val);33static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val);
634
7bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {35bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
...@@ -94,9 +122,9 @@ static bool eval_return(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -94,9 +122,9 @@ static bool eval_return(EvalFn *ef, AstNode *node, ConstExprValue *out) {
94}122}
95123
96static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {124static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
97 if (bin_op == BinOpTypeBoolOr) {125 if (bin_op == BinOpTypeBoolOr || bin_op == BinOpTypeAssignBoolOr) {
98 return a || b;126 return a || b;
99 } else if (bin_op == BinOpTypeBoolAnd) {127 } else if (bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeAssignBoolAnd) {
100 return a && b;128 return a && b;
101 } else {129 } else {
102 zig_unreachable();130 zig_unreachable();
...@@ -180,6 +208,31 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue...@@ -180,6 +208,31 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
180 return 0;208 return 0;
181}209}
182210
211bool eval_const_expr_bin_op_handle_errors(EvalFn *ef, AstNode *node,
212 ConstExprValue *op1_val, TypeTableEntry *op1_type,
213 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
214{
215 int err;
216 if ((err = eval_const_expr_bin_op(op1_val, op1_type, bin_op, op2_val, op2_type, out_val))) {
217 ef->root->abort = true;
218 if (err == ErrorDivByZero) {
219 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
220 buf_sprintf("function evaluation caused division by zero"));
221 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
222 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
223 } else if (err == ErrorOverflow) {
224 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
225 buf_sprintf("function evaluation caused overflow"));
226 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
227 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
228 } else {
229 zig_unreachable();
230 }
231 return true;
232 }
233 return false;
234}
235
183int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,236int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
184 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)237 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
185{238{
...@@ -190,25 +243,12 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -190,25 +243,12 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
190243
191 switch (bin_op) {244 switch (bin_op) {
192 case BinOpTypeAssign:245 case BinOpTypeAssign:
193 case BinOpTypeAssignTimes:246 *out_val = *op2_val;
194 case BinOpTypeAssignTimesWrap:247 return 0;
195 case BinOpTypeAssignDiv:
196 case BinOpTypeAssignMod:
197 case BinOpTypeAssignPlus:
198 case BinOpTypeAssignPlusWrap:
199 case BinOpTypeAssignMinus:
200 case BinOpTypeAssignMinusWrap:
201 case BinOpTypeAssignBitShiftLeft:
202 case BinOpTypeAssignBitShiftLeftWrap:
203 case BinOpTypeAssignBitShiftRight:
204 case BinOpTypeAssignBitAnd:
205 case BinOpTypeAssignBitXor:
206 case BinOpTypeAssignBitOr:
207 case BinOpTypeAssignBoolAnd:
208 case BinOpTypeAssignBoolOr:
209 zig_unreachable();
210 case BinOpTypeBoolOr:248 case BinOpTypeBoolOr:
211 case BinOpTypeBoolAnd:249 case BinOpTypeBoolAnd:
250 case BinOpTypeAssignBoolAnd:
251 case BinOpTypeAssignBoolOr:
212 assert(op1_type->id == TypeTableEntryIdBool);252 assert(op1_type->id == TypeTableEntryIdBool);
213 assert(op2_type->id == TypeTableEntryIdBool);253 assert(op2_type->id == TypeTableEntryIdBool);
214 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);254 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
...@@ -264,30 +304,43 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -264,30 +304,43 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
264 return 0;304 return 0;
265 }305 }
266 case BinOpTypeAdd:306 case BinOpTypeAdd:
307 case BinOpTypeAssignPlus:
267 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false);308 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, false);
268 case BinOpTypeAddWrap:309 case BinOpTypeAddWrap:
310 case BinOpTypeAssignPlusWrap:
269 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true);311 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add, op1_type, true);
270 case BinOpTypeBinOr:312 case BinOpTypeBinOr:
313 case BinOpTypeAssignBitOr:
271 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false);314 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or, op1_type, false);
272 case BinOpTypeBinXor:315 case BinOpTypeBinXor:
316 case BinOpTypeAssignBitXor:
273 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false);317 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor, op1_type, false);
274 case BinOpTypeBinAnd:318 case BinOpTypeBinAnd:
319 case BinOpTypeAssignBitAnd:
275 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false);320 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and, op1_type, false);
276 case BinOpTypeBitShiftLeft:321 case BinOpTypeBitShiftLeft:
322 case BinOpTypeAssignBitShiftLeft:
277 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false);323 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, false);
278 case BinOpTypeBitShiftLeftWrap:324 case BinOpTypeBitShiftLeftWrap:
325 case BinOpTypeAssignBitShiftLeftWrap:
279 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true);326 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl, op1_type, true);
280 case BinOpTypeBitShiftRight:327 case BinOpTypeBitShiftRight:
328 case BinOpTypeAssignBitShiftRight:
281 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false);329 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr, op1_type, false);
282 case BinOpTypeSub:330 case BinOpTypeSub:
331 case BinOpTypeAssignMinus:
283 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false);332 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, false);
284 case BinOpTypeSubWrap:333 case BinOpTypeSubWrap:
334 case BinOpTypeAssignMinusWrap:
285 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true);335 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub, op1_type, true);
286 case BinOpTypeMult:336 case BinOpTypeMult:
337 case BinOpTypeAssignTimes:
287 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false);338 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, false);
288 case BinOpTypeMultWrap:339 case BinOpTypeMultWrap:
340 case BinOpTypeAssignTimesWrap:
289 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true);341 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul, op1_type, true);
290 case BinOpTypeDiv:342 case BinOpTypeDiv:
343 case BinOpTypeAssignDiv:
291 {344 {
292 bool is_int = false;345 bool is_int = false;
293 bool is_float = false;346 bool is_float = false;
...@@ -309,6 +362,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -309,6 +362,7 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
309 }362 }
310 }363 }
311 case BinOpTypeMod:364 case BinOpTypeMod:
365 case BinOpTypeAssignMod:
312 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false);366 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod, op1_type, false);
313 case BinOpTypeUnwrapMaybe:367 case BinOpTypeUnwrapMaybe:
314 zig_panic("TODO");368 zig_panic("TODO");
...@@ -320,13 +374,66 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -320,13 +374,66 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
320 zig_unreachable();374 zig_unreachable();
321}375}
322376
323static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {377static EvalVar *find_var(EvalFn *ef, Buf *name) {
324 assert(node->type == NodeTypeBinOpExpr);378 size_t scope_index = ef->scope_stack.length - 1;
379 while (scope_index != SIZE_MAX) {
380 EvalScope *scope = ef->scope_stack.at(scope_index);
381 for (size_t var_i = 0; var_i < scope->vars.length; var_i += 1) {
382 EvalVar *var = &scope->vars.at(var_i);
383 if (buf_eql_buf(var->name, name)) {
384 return var;
385 }
386 }
387 scope_index -= 1;
388 }
325389
390 return nullptr;
391}
392
393static bool eval_get_lvalue(EvalFn *ef, AstNode *node, ConstExprValue **lvalue) {
394 if (node->type == NodeTypeSymbol) {
395 Buf *name = node->data.symbol_expr.symbol;
396 EvalVar *var = find_var(ef, name);
397 assert(var);
398 *lvalue = &var->value;
399 } else {
400 zig_panic("TODO eval other lvalue types");
401 }
402 return false;
403}
404
405static bool eval_bin_op_assign(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
326 AstNode *op1 = node->data.bin_op_expr.op1;406 AstNode *op1 = node->data.bin_op_expr.op1;
327 AstNode *op2 = node->data.bin_op_expr.op2;407 AstNode *op2 = node->data.bin_op_expr.op2;
328 BinOpType bin_op = node->data.bin_op_expr.bin_op;408 BinOpType bin_op = node->data.bin_op_expr.bin_op;
329409
410 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;
411 assert(op2_type);
412
413 ConstExprValue *assign_result_val;
414 if (eval_get_lvalue(ef, op1, &assign_result_val)) return true;
415
416 ConstExprValue op1_val = *assign_result_val;
417
418 ConstExprValue op2_val = {0};
419 if (eval_expr(ef, op2, &op2_val)) return true;
420
421 if (eval_const_expr_bin_op_handle_errors(ef, node, &op1_val, op2_type, bin_op, &op2_val, op2_type,
422 assign_result_val))
423 {
424 return true;
425 }
426
427 out_val->ok = true;
428 out_val->depends_on_compile_var = false;
429 return false;
430}
431
432static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
433 assert(node->type == NodeTypeBinOpExpr);
434
435 BinOpType bin_op = node->data.bin_op_expr.bin_op;
436
330 switch (bin_op) {437 switch (bin_op) {
331 case BinOpTypeAssign:438 case BinOpTypeAssign:
332 case BinOpTypeAssignTimes:439 case BinOpTypeAssignTimes:
...@@ -345,7 +452,7 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)...@@ -345,7 +452,7 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
345 case BinOpTypeAssignBitOr:452 case BinOpTypeAssignBitOr:
346 case BinOpTypeAssignBoolAnd:453 case BinOpTypeAssignBoolAnd:
347 case BinOpTypeAssignBoolOr:454 case BinOpTypeAssignBoolOr:
348 zig_panic("TODO");455 return eval_bin_op_assign(ef, node, out_val);
349 case BinOpTypeBoolOr:456 case BinOpTypeBoolOr:
350 case BinOpTypeBoolAnd:457 case BinOpTypeBoolAnd:
351 case BinOpTypeCmpEq:458 case BinOpTypeCmpEq:
...@@ -376,6 +483,10 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)...@@ -376,6 +483,10 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
376 zig_unreachable();483 zig_unreachable();
377 }484 }
378485
486 AstNode *op1 = node->data.bin_op_expr.op1;
487 AstNode *op2 = node->data.bin_op_expr.op2;
488
489
379 TypeTableEntry *op1_type = get_resolved_expr(op1)->type_entry;490 TypeTableEntry *op1_type = get_resolved_expr(op1)->type_entry;
380 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;491 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;
381492
...@@ -388,22 +499,7 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)...@@ -388,22 +499,7 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
388 ConstExprValue op2_val = {0};499 ConstExprValue op2_val = {0};
389 if (eval_expr(ef, op2, &op2_val)) return true;500 if (eval_expr(ef, op2, &op2_val)) return true;
390501
391 int err;502 if (eval_const_expr_bin_op_handle_errors(ef, node, &op1_val, op1_type, bin_op, &op2_val, op2_type, out_val)) {
392 if ((err = eval_const_expr_bin_op(&op1_val, op1_type, bin_op, &op2_val, op2_type, out_val))) {
393 ef->root->abort = true;
394 if (err == ErrorDivByZero) {
395 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
396 buf_sprintf("function evaluation caused division by zero"));
397 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
398 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
399 } else if (err == ErrorOverflow) {
400 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
401 buf_sprintf("function evaluation caused overflow"));
402 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
403 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
404 } else {
405 zig_unreachable();
406 }
407 return true;503 return true;
408 }504 }
409505
...@@ -412,22 +508,6 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)...@@ -412,22 +508,6 @@ static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
412 return false;508 return false;
413}509}
414510
415static EvalVar *find_var(EvalFn *ef, Buf *name) {
416 size_t scope_index = ef->scope_stack.length - 1;
417 while (scope_index != SIZE_MAX) {
418 EvalScope *scope = ef->scope_stack.at(scope_index);
419 for (size_t var_i = 0; var_i < scope->vars.length; var_i += 1) {
420 EvalVar *var = &scope->vars.at(var_i);
421 if (buf_eql_buf(var->name, name)) {
422 return var;
423 }
424 }
425 scope_index -= 1;
426 }
427
428 return nullptr;
429}
430
431static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {511static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
432 assert(node->type == NodeTypeSymbol);512 assert(node->type == NodeTypeSymbol);
433513
...@@ -456,7 +536,7 @@ static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *...@@ -456,7 +536,7 @@ static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *
456 ContainerInitKind kind = container_init_expr->kind;536 ContainerInitKind kind = container_init_expr->kind;
457537
458 if (container_init_expr->enum_type) {538 if (container_init_expr->enum_type) {
459 zig_panic("TODO");539 zig_panic("TODO eval enum init");
460 }540 }
461541
462 TypeTableEntry *container_type = resolve_expr_type(container_init_expr->type);542 TypeTableEntry *container_type = resolve_expr_type(container_init_expr->type);
...@@ -514,7 +594,7 @@ static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *...@@ -514,7 +594,7 @@ static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *
514 elem_val->depends_on_compile_var;594 elem_val->depends_on_compile_var;
515 }595 }
516 } else {596 } else {
517 zig_panic("TODO");597 zig_panic("TODO init more container kinds");
518 }598 }
519599
520600
...@@ -874,7 +954,7 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_...@@ -874,7 +954,7 @@ static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_
874 case BuiltinFnIdEmbedFile:954 case BuiltinFnIdEmbedFile:
875 case BuiltinFnIdCmpExchange:955 case BuiltinFnIdCmpExchange:
876 case BuiltinFnIdTruncate:956 case BuiltinFnIdTruncate:
877 zig_panic("TODO");957 zig_panic("TODO builtin function");
878 case BuiltinFnIdBreakpoint:958 case BuiltinFnIdBreakpoint:
879 case BuiltinFnIdInvalid:959 case BuiltinFnIdInvalid:
880 case BuiltinFnIdFrameAddress:960 case BuiltinFnIdFrameAddress:
...@@ -909,7 +989,7 @@ static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val...@@ -909,7 +989,7 @@ static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val
909 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&989 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
910 fn_ref_expr->data.field_access_expr.is_member_fn)990 fn_ref_expr->data.field_access_expr.is_member_fn)
911 {991 {
912 zig_panic("TODO");992 zig_panic("TODO field access member fn");
913 }993 }
914994
915 if (!fn_table_entry) {995 if (!fn_table_entry) {
...@@ -941,7 +1021,7 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -941,7 +1021,7 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
941 if (struct_type->id == TypeTableEntryIdArray) {1021 if (struct_type->id == TypeTableEntryIdArray) {
942 Buf *name = node->data.field_access_expr.field_name;1022 Buf *name = node->data.field_access_expr.field_name;
943 assert(buf_eql_str(name, "len"));1023 assert(buf_eql_str(name, "len"));
944 zig_panic("TODO");1024 zig_panic("TODO field access array");
945 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&1025 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
946 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))1026 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
947 {1027 {
...@@ -954,17 +1034,17 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -954,17 +1034,17 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
954 *out_val = *field_value;1034 *out_val = *field_value;
955 assert(out_val->ok);1035 assert(out_val->ok);
956 } else {1036 } else {
957 zig_panic("TODO");1037 zig_panic("TODO field access struct");
958 }1038 }
959 } else if (struct_type->id == TypeTableEntryIdMetaType) {1039 } else if (struct_type->id == TypeTableEntryIdMetaType) {
960 TypeTableEntry *child_type = resolve_expr_type(struct_expr);1040 TypeTableEntry *child_type = resolve_expr_type(struct_expr);
961 if (child_type->id == TypeTableEntryIdPureError) {1041 if (child_type->id == TypeTableEntryIdPureError) {
962 *out_val = get_resolved_expr(node)->const_val;1042 *out_val = get_resolved_expr(node)->const_val;
963 } else {1043 } else {
964 zig_panic("TODO");1044 zig_panic("TODO field access meta type");
965 }1045 }
966 } else if (struct_type->id == TypeTableEntryIdNamespace) {1046 } else if (struct_type->id == TypeTableEntryIdNamespace) {
967 zig_panic("TODO");1047 zig_panic("TODO field access namespace");
968 } else {1048 } else {
969 zig_unreachable();1049 zig_unreachable();
970 }1050 }
...@@ -989,7 +1069,7 @@ static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {...@@ -989,7 +1069,7 @@ static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
989 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;1069 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
9901070
991 if (node->data.for_expr.elem_is_ptr) {1071 if (node->data.for_expr.elem_is_ptr) {
992 zig_panic("TODO");1072 zig_panic("TODO for elem is ptr");
993 }1073 }
9941074
995 Buf *index_var_name = nullptr;1075 Buf *index_var_name = nullptr;
...@@ -1062,7 +1142,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -1062,7 +1142,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
10621142
1063 if (array_type->id == TypeTableEntryIdPointer) {1143 if (array_type->id == TypeTableEntryIdPointer) {
1064 if (index_int >= array_val.data.x_ptr.len) {1144 if (index_int >= array_val.data.x_ptr.len) {
1065 zig_panic("TODO");1145 zig_panic("TODO array access pointer");
1066 }1146 }
1067 *out_val = *array_val.data.x_ptr.ptr[index_int];1147 *out_val = *array_val.data.x_ptr.ptr[index_int];
1068 } else if (array_type->id == TypeTableEntryIdStruct) {1148 } else if (array_type->id == TypeTableEntryIdStruct) {
...@@ -1071,7 +1151,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -1071,7 +1151,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
1071 ConstExprValue *len_value = array_val.data.x_struct.fields[1];1151 ConstExprValue *len_value = array_val.data.x_struct.fields[1];
1072 uint64_t len_int = len_value->data.x_bignum.data.x_uint;1152 uint64_t len_int = len_value->data.x_bignum.data.x_uint;
1073 if (index_int >= len_int) {1153 if (index_int >= len_int) {
1074 zig_panic("TODO");1154 zig_panic("TODO array access slice");
1075 }1155 }
10761156
1077 ConstExprValue *ptr_value = array_val.data.x_struct.fields[0];1157 ConstExprValue *ptr_value = array_val.data.x_struct.fields[0];
...@@ -1079,7 +1159,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -1079,7 +1159,7 @@ static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
1079 } else if (array_type->id == TypeTableEntryIdArray) {1159 } else if (array_type->id == TypeTableEntryIdArray) {
1080 uint64_t array_len = array_type->data.array.len;1160 uint64_t array_len = array_type->data.array.len;
1081 if (index_int >= array_len) {1161 if (index_int >= array_len) {
1082 zig_panic("TODO");1162 zig_panic("TODO array access array");
1083 }1163 }
1084 *out_val = *array_val.data.x_array.fields[index_int];1164 *out_val = *array_val.data.x_array.fields[index_int];
1085 } else {1165 } else {
...@@ -1152,7 +1232,7 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v...@@ -1152,7 +1232,7 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v
1152 return true;1232 return true;
1153 }1233 }
1154 } else if (expr_type->id == TypeTableEntryIdFloat) {1234 } else if (expr_type->id == TypeTableEntryIdFloat) {
1155 zig_panic("TODO");1235 zig_panic("TODO prefix op on floats");
1156 } else {1236 } else {
1157 zig_unreachable();1237 zig_unreachable();
1158 }1238 }
...@@ -1162,7 +1242,7 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v...@@ -1162,7 +1242,7 @@ static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_v
1162 case PrefixOpError:1242 case PrefixOpError:
1163 case PrefixOpUnwrapError:1243 case PrefixOpUnwrapError:
1164 case PrefixOpUnwrapMaybe:1244 case PrefixOpUnwrapMaybe:
1165 zig_panic("TODO");1245 zig_panic("TODO more prefix operations");
1166 case PrefixOpInvalid:1246 case PrefixOpInvalid:
1167 zig_unreachable();1247 zig_unreachable();
1168 }1248 }
...@@ -1308,7 +1388,7 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -1308,7 +1388,7 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
1308 case NodeTypeErrorType:1388 case NodeTypeErrorType:
1309 case NodeTypeTypeLiteral:1389 case NodeTypeTypeLiteral:
1310 case NodeTypeVarLiteral:1390 case NodeTypeVarLiteral:
1311 zig_panic("TODO");1391 zig_panic("TODO expr node");
1312 case NodeTypeRoot:1392 case NodeTypeRoot:
1313 case NodeTypeFnProto:1393 case NodeTypeFnProto:
1314 case NodeTypeFnDef:1394 case NodeTypeFnDef:
std/cstr.zig+18-8
...@@ -6,22 +6,22 @@ const assert = debug.assert;...@@ -6,22 +6,22 @@ const assert = debug.assert;
66
7const strlen = len;7const strlen = len;
88
9// TODO fix https://github.com/andrewrk/zig/issues/140
10// and then make this able to run at compile time
11#static_eval_enable(false)
12pub fn len(ptr: &const u8) -> usize {9pub fn len(ptr: &const u8) -> usize {
13 var count: usize = 0;10 var count: usize = 0;
14 while (ptr[count] != 0; count += 1) {}11 while (ptr[count] != 0; count += 1) {}
15 return count;12 return count;
16}13}
1714
18// TODO fix https://github.com/andrewrk/zig/issues/14015pub fn cmp(a: &const u8, b: &const u8) -> i8 {
19// and then make this able to run at compile time
20#static_eval_enable(false)
21pub fn cmp(a: &const u8, b: &const u8) -> i32 {
22 var index: usize = 0;16 var index: usize = 0;
23 while (a[index] == b[index] && a[index] != 0; index += 1) {}17 while (a[index] == b[index] && a[index] != 0; index += 1) {}
24 return a[index] - b[index];18 return if (a[index] > b[index]) {
19 1
20 } else if (a[index] < b[index]) {
21 -1
22 } else {
23 0
24 };
25}25}
2626
27pub fn toSliceConst(str: &const u8) -> []const u8 {27pub fn toSliceConst(str: &const u8) -> []const u8 {
...@@ -145,3 +145,13 @@ fn testSimpleCBuf() {...@@ -145,3 +145,13 @@ fn testSimpleCBuf() {
145 %%buf2.resize(4);145 %%buf2.resize(4);
146 assert(buf.startsWithCBuf(&buf2));146 assert(buf.startsWithCBuf(&buf2));
147}147}
148
149#attribute("test")
150fn testCompileTimeStrCmp() {
151 assert(@constEval(cmp(c"aoeu", c"aoez") == -1));
152}
153
154#attribute("test")
155fn testCompileTimeStrLen() {
156 assert(@constEval(len(c"123456789") == 9));
157}