authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-17 00:44:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-17 00:44:14-05:00
loga55555c99e9bcc1424c8650ab44570caf593bcdc
treeca13e7fd6e520560b32d49a3acec05c3e05958a0
parent8d1c6138f950d7ce44d823ce870643b94b19ffb1

remove superseded eval code


2 files changed, 0 insertions(+), 1010 deletions(-)

src/eval.cpp-1007
...@@ -2,36 +2,6 @@...@@ -2,36 +2,6 @@
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
33static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val);
34
35bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {5bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
36 switch (type_entry->id) {6 switch (type_entry->id) {
37 case TypeTableEntryIdEnum:7 case TypeTableEntryIdEnum:
...@@ -95,33 +65,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty...@@ -95,33 +65,6 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty
95}65}
9666
9767
98static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out);
99
100static bool eval_block(EvalFn *ef, AstNode *node, ConstExprValue *out) {
101 assert(node->type == NodeTypeBlock);
102
103 EvalScope *my_scope = allocate<EvalScope>(1);
104 my_scope->block_context = node->block_context;
105 ef->scope_stack.append(my_scope);
106
107 for (size_t i = 0; i < node->data.block.statements.length; i += 1) {
108 AstNode *child = node->data.block.statements.at(i);
109 memset(out, 0, sizeof(ConstExprValue));
110 if (eval_expr(ef, child, out)) return true;
111 }
112
113 ef->scope_stack.pop();
114
115 return false;
116}
117
118static bool eval_return(EvalFn *ef, AstNode *node, ConstExprValue *out) {
119 assert(node->type == NodeTypeReturnExpr);
120
121 eval_expr(ef, node->data.return_expr.expr, ef->return_expr);
122 return true;
123}
124
125static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {68static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
126 if (bin_op == BinOpTypeBoolOr || bin_op == BinOpTypeAssignBoolOr) {69 if (bin_op == BinOpTypeBoolOr || bin_op == BinOpTypeAssignBoolOr) {
127 return a || b;70 return a || b;
...@@ -209,31 +152,6 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue...@@ -209,31 +152,6 @@ static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue
209 return 0;152 return 0;
210}153}
211154
212bool eval_const_expr_bin_op_handle_errors(EvalFn *ef, AstNode *node,
213 ConstExprValue *op1_val, TypeTableEntry *op1_type,
214 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
215{
216 int err;
217 if ((err = eval_const_expr_bin_op(op1_val, op1_type, bin_op, op2_val, op2_type, out_val))) {
218 ef->root->abort = true;
219 if (err == ErrorDivByZero) {
220 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
221 buf_sprintf("function evaluation caused division by zero"));
222 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
223 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
224 } else if (err == ErrorOverflow) {
225 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
226 buf_sprintf("function evaluation caused overflow"));
227 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
228 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
229 } else {
230 zig_unreachable();
231 }
232 return true;
233 }
234 return false;
235}
236
237int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,155int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
238 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)156 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
239{157{
...@@ -375,249 +293,6 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -375,249 +293,6 @@ int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
375 zig_unreachable();293 zig_unreachable();
376}294}
377295
378static EvalVar *find_var(EvalFn *ef, Buf *name) {
379 size_t scope_index = ef->scope_stack.length - 1;
380 while (scope_index != SIZE_MAX) {
381 EvalScope *scope = ef->scope_stack.at(scope_index);
382 for (size_t var_i = 0; var_i < scope->vars.length; var_i += 1) {
383 EvalVar *var = &scope->vars.at(var_i);
384 if (buf_eql_buf(var->name, name)) {
385 return var;
386 }
387 }
388 scope_index -= 1;
389 }
390
391 return nullptr;
392}
393
394static bool eval_get_lvalue(EvalFn *ef, AstNode *node, ConstExprValue **lvalue) {
395 if (node->type == NodeTypeSymbol) {
396 Buf *name = node->data.symbol_expr.symbol;
397 EvalVar *var = find_var(ef, name);
398 assert(var);
399 *lvalue = &var->value;
400 } else {
401 zig_panic("TODO eval other lvalue types");
402 }
403 return false;
404}
405
406static bool eval_bin_op_assign(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
407 AstNode *op1 = node->data.bin_op_expr.op1;
408 AstNode *op2 = node->data.bin_op_expr.op2;
409 BinOpType bin_op = node->data.bin_op_expr.bin_op;
410
411 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;
412 assert(op2_type);
413
414 ConstExprValue *assign_result_val;
415 if (eval_get_lvalue(ef, op1, &assign_result_val)) return true;
416
417 ConstExprValue op1_val = *assign_result_val;
418
419 ConstExprValue op2_val = {0};
420 if (eval_expr(ef, op2, &op2_val)) return true;
421
422 if (eval_const_expr_bin_op_handle_errors(ef, node, &op1_val, op2_type, bin_op, &op2_val, op2_type,
423 assign_result_val))
424 {
425 return true;
426 }
427
428 out_val->ok = true;
429 out_val->depends_on_compile_var = false;
430 return false;
431}
432
433static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
434 assert(node->type == NodeTypeBinOpExpr);
435
436 BinOpType bin_op = node->data.bin_op_expr.bin_op;
437
438 switch (bin_op) {
439 case BinOpTypeAssign:
440 case BinOpTypeAssignTimes:
441 case BinOpTypeAssignTimesWrap:
442 case BinOpTypeAssignDiv:
443 case BinOpTypeAssignMod:
444 case BinOpTypeAssignPlus:
445 case BinOpTypeAssignPlusWrap:
446 case BinOpTypeAssignMinus:
447 case BinOpTypeAssignMinusWrap:
448 case BinOpTypeAssignBitShiftLeft:
449 case BinOpTypeAssignBitShiftLeftWrap:
450 case BinOpTypeAssignBitShiftRight:
451 case BinOpTypeAssignBitAnd:
452 case BinOpTypeAssignBitXor:
453 case BinOpTypeAssignBitOr:
454 case BinOpTypeAssignBoolAnd:
455 case BinOpTypeAssignBoolOr:
456 return eval_bin_op_assign(ef, node, out_val);
457 case BinOpTypeBoolOr:
458 case BinOpTypeBoolAnd:
459 case BinOpTypeCmpEq:
460 case BinOpTypeCmpNotEq:
461 case BinOpTypeCmpLessThan:
462 case BinOpTypeCmpGreaterThan:
463 case BinOpTypeCmpLessOrEq:
464 case BinOpTypeCmpGreaterOrEq:
465 case BinOpTypeBinOr:
466 case BinOpTypeBinXor:
467 case BinOpTypeBinAnd:
468 case BinOpTypeBitShiftLeft:
469 case BinOpTypeBitShiftLeftWrap:
470 case BinOpTypeBitShiftRight:
471 case BinOpTypeAdd:
472 case BinOpTypeAddWrap:
473 case BinOpTypeSub:
474 case BinOpTypeSubWrap:
475 case BinOpTypeMult:
476 case BinOpTypeMultWrap:
477 case BinOpTypeDiv:
478 case BinOpTypeMod:
479 case BinOpTypeUnwrapMaybe:
480 case BinOpTypeArrayCat:
481 case BinOpTypeArrayMult:
482 break;
483 case BinOpTypeInvalid:
484 zig_unreachable();
485 }
486
487 AstNode *op1 = node->data.bin_op_expr.op1;
488 AstNode *op2 = node->data.bin_op_expr.op2;
489
490
491 TypeTableEntry *op1_type = get_resolved_expr(op1)->type_entry;
492 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;
493
494 assert(op1_type);
495 assert(op2_type);
496
497 ConstExprValue op1_val = {0};
498 if (eval_expr(ef, op1, &op1_val)) return true;
499
500 ConstExprValue op2_val = {0};
501 if (eval_expr(ef, op2, &op2_val)) return true;
502
503 if (eval_const_expr_bin_op_handle_errors(ef, node, &op1_val, op1_type, bin_op, &op2_val, op2_type, out_val)) {
504 return true;
505 }
506
507 assert(out_val->ok);
508
509 return false;
510}
511
512static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
513 assert(node->type == NodeTypeSymbol);
514
515 Buf *name = node->data.symbol_expr.symbol;
516 EvalVar *var = find_var(ef, name);
517 assert(var);
518
519 *out_val = var->value;
520
521 return false;
522}
523
524static TypeTableEntry *resolve_expr_type(AstNode *node) {
525 Expr *expr = get_resolved_expr(node);
526 TypeTableEntry *type_entry = expr->type_entry;
527 assert(type_entry->id == TypeTableEntryIdMetaType);
528 ConstExprValue *const_val = &expr->const_val;
529 assert(const_val->ok);
530 return const_val->data.x_type;
531}
532
533static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
534 assert(node->type == NodeTypeContainerInitExpr);
535
536 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
537 ContainerInitKind kind = container_init_expr->kind;
538
539 if (container_init_expr->enum_type) {
540 zig_panic("TODO eval enum init");
541 }
542
543 TypeTableEntry *container_type = resolve_expr_type(container_init_expr->type);
544 out_val->ok = true;
545
546 if (container_type->id == TypeTableEntryIdStruct &&
547 !container_type->data.structure.is_slice &&
548 kind == ContainerInitKindStruct)
549 {
550 size_t expr_field_count = container_init_expr->entries.length;
551 size_t actual_field_count = container_type->data.structure.src_field_count;
552 assert(expr_field_count == actual_field_count);
553
554 out_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
555
556 for (size_t i = 0; i < expr_field_count; i += 1) {
557 AstNode *val_field_node = container_init_expr->entries.at(i);
558 assert(val_field_node->type == NodeTypeStructValueField);
559
560 TypeStructField *type_field = val_field_node->data.struct_val_field.type_struct_field;
561 size_t field_index = type_field->src_index;
562
563 ConstExprValue src_field_val = {0};
564 if (eval_expr(ef, val_field_node->data.struct_val_field.expr, &src_field_val)) return true;
565
566 ConstExprValue *dest_field_val = allocate<ConstExprValue>(1);
567 *dest_field_val = src_field_val;
568
569 out_val->data.x_struct.fields[field_index] = dest_field_val;
570 out_val->depends_on_compile_var = out_val->depends_on_compile_var ||
571 src_field_val.depends_on_compile_var;
572 }
573 } else if (container_type->id == TypeTableEntryIdVoid) {
574 return false;
575 } else if (container_type->id == TypeTableEntryIdStruct &&
576 container_type->data.structure.is_slice &&
577 kind == ContainerInitKindArray)
578 {
579
580 size_t elem_count = container_init_expr->entries.length;
581
582 out_val->ok = true;
583 out_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
584
585 for (size_t i = 0; i < elem_count; i += 1) {
586 AstNode *elem_node = container_init_expr->entries.at(i);
587
588 ConstExprValue *elem_val = allocate<ConstExprValue>(1);
589 if (eval_expr(ef, elem_node, elem_val)) return true;
590
591 assert(elem_val->ok);
592
593 out_val->data.x_array.fields[i] = elem_val;
594 out_val->depends_on_compile_var = out_val->depends_on_compile_var ||
595 elem_val->depends_on_compile_var;
596 }
597 } else {
598 zig_panic("TODO init more container kinds");
599 }
600
601
602 return false;
603}
604
605static bool eval_if_bool_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
606 assert(node->type == NodeTypeIfBoolExpr);
607
608 ConstExprValue cond_val = {0};
609 if (eval_expr(ef, node->data.if_bool_expr.condition, &cond_val)) return true;
610
611 AstNode *exec_node = cond_val.data.x_bool ?
612 node->data.if_bool_expr.then_block : node->data.if_bool_expr.else_node;
613
614 if (exec_node) {
615 if (eval_expr(ef, exec_node, out_val)) return true;
616 }
617 out_val->ok = true;
618 return false;
619}
620
621void eval_const_expr_implicit_cast(CastOp cast_op,296void eval_const_expr_implicit_cast(CastOp cast_op,
622 ConstExprValue *other_val, TypeTableEntry *other_type,297 ConstExprValue *other_val, TypeTableEntry *other_type,
623 ConstExprValue *const_val, TypeTableEntry *new_type)298 ConstExprValue *const_val, TypeTableEntry *new_type)
...@@ -817,685 +492,3 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *...@@ -817,685 +492,3 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
817 zig_unreachable();492 zig_unreachable();
818 }493 }
819}494}
820
821static bool eval_min_max(EvalFn *ef, AstNode *node, ConstExprValue *out_val, bool is_max) {
822 assert(node->type == NodeTypeFnCallExpr);
823 AstNode *type_node = node->data.fn_call_expr.params.at(0);
824 TypeTableEntry *type_entry = resolve_expr_type(type_node);
825 eval_min_max_value(ef->root->codegen, type_entry, out_val, is_max);
826 return false;
827}
828
829static bool eval_div_exact(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
830 assert(node->type == NodeTypeFnCallExpr);
831 AstNode *op1_node = node->data.fn_call_expr.params.at(0);
832 AstNode *op2_node = node->data.fn_call_expr.params.at(1);
833
834 TypeTableEntry *type_entry = get_resolved_expr(op1_node)->type_entry;
835 assert(type_entry->id == TypeTableEntryIdInt);
836
837 ConstExprValue op1_val = {0};
838 if (eval_expr(ef, op1_node, &op1_val)) return true;
839
840 ConstExprValue op2_val = {0};
841 if (eval_expr(ef, op2_node, &op2_val)) return true;
842
843 if (op2_val.data.x_bignum.data.x_uint == 0) {
844 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
845 buf_sprintf("function evaluation caused division by zero"));
846 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
847 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
848 return true;
849 }
850
851 bignum_div(&out_val->data.x_bignum, &op1_val.data.x_bignum, &op2_val.data.x_bignum);
852
853 BigNum orig_bn;
854 bignum_mul(&orig_bn, &out_val->data.x_bignum, &op2_val.data.x_bignum);
855
856 if (bignum_cmp_neq(&orig_bn, &op1_val.data.x_bignum)) {
857 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
858 buf_sprintf("function evaluation violated exact division"));
859 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
860 add_error_note(ef->root->codegen, msg, node, buf_sprintf("exact division violation here"));
861 return true;
862 }
863
864 out_val->ok = true;
865 out_val->depends_on_compile_var = op1_val.depends_on_compile_var || op2_val.depends_on_compile_var;
866 return false;
867}
868
869static bool eval_unreachable(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
870 ef->root->abort = true;
871 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
872 buf_sprintf("function evaluation reached unreachable expression"));
873 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
874 add_error_note(ef->root->codegen, msg, node, buf_sprintf("unreachable expression here"));
875 return true;
876}
877
878static bool eval_fn_with_overflow(EvalFn *ef, AstNode *node, ConstExprValue *out_val,
879 bool (*bignum_fn)(BigNum *dest, BigNum *op1, BigNum *op2))
880{
881 assert(node->type == NodeTypeFnCallExpr);
882
883 AstNode *type_node = node->data.fn_call_expr.params.at(0);
884 TypeTableEntry *int_type = resolve_expr_type(type_node);
885 assert(int_type->id == TypeTableEntryIdInt);
886
887 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
888 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
889 AstNode *result_node = node->data.fn_call_expr.params.at(3);
890
891 ConstExprValue op1_val = {0};
892 if (eval_expr(ef, op1_node, &op1_val)) return true;
893
894 ConstExprValue op2_val = {0};
895 if (eval_expr(ef, op2_node, &op2_val)) return true;
896
897 ConstExprValue result_ptr_val = {0};
898 if (eval_expr(ef, result_node, &result_ptr_val)) return true;
899
900 ConstExprValue *result_val = result_ptr_val.data.x_ptr.ptr[0];
901
902 out_val->ok = true;
903 bool overflow = bignum_fn(&result_val->data.x_bignum, &op1_val.data.x_bignum, &op2_val.data.x_bignum);
904
905 overflow = overflow || !bignum_fits_in_bits(&result_val->data.x_bignum,
906 int_type->data.integral.bit_count, int_type->data.integral.is_signed);
907
908 out_val->data.x_bool = overflow;
909
910 if (overflow) {
911 bignum_truncate(&result_val->data.x_bignum, int_type->data.integral.bit_count);
912 }
913
914 return false;
915}
916
917static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
918 assert(node->type == NodeTypeFnCallExpr);
919
920 BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
921 switch (builtin_fn->id) {
922 case BuiltinFnIdMaxValue:
923 return eval_min_max(ef, node, out_val, true);
924 case BuiltinFnIdMinValue:
925 return eval_min_max(ef, node, out_val, false);
926 case BuiltinFnIdMulWithOverflow:
927 return eval_fn_with_overflow(ef, node, out_val, bignum_mul);
928 case BuiltinFnIdAddWithOverflow:
929 return eval_fn_with_overflow(ef, node, out_val, bignum_add);
930 case BuiltinFnIdSubWithOverflow:
931 return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
932 case BuiltinFnIdShlWithOverflow:
933 return eval_fn_with_overflow(ef, node, out_val, bignum_shl);
934 case BuiltinFnIdFence:
935 return false;
936 case BuiltinFnIdDivExact:
937 return eval_div_exact(ef, node, out_val);
938 case BuiltinFnIdUnreachable:
939 return eval_unreachable(ef, node, out_val);
940 case BuiltinFnIdMemcpy:
941 case BuiltinFnIdMemset:
942 case BuiltinFnIdSizeof:
943 case BuiltinFnIdAlignof:
944 case BuiltinFnIdMemberCount:
945 case BuiltinFnIdTypeof:
946 case BuiltinFnIdCInclude:
947 case BuiltinFnIdCDefine:
948 case BuiltinFnIdCUndef:
949 case BuiltinFnIdCompileVar:
950 case BuiltinFnIdConstEval:
951 case BuiltinFnIdCtz:
952 case BuiltinFnIdClz:
953 case BuiltinFnIdImport:
954 case BuiltinFnIdCImport:
955 case BuiltinFnIdErrName:
956 case BuiltinFnIdEmbedFile:
957 case BuiltinFnIdCmpExchange:
958 case BuiltinFnIdTruncate:
959 zig_panic("TODO builtin function");
960 case BuiltinFnIdBreakpoint:
961 case BuiltinFnIdInvalid:
962 case BuiltinFnIdFrameAddress:
963 case BuiltinFnIdReturnAddress:
964 case BuiltinFnIdCompileErr:
965 case BuiltinFnIdIntType:
966 zig_unreachable();
967 case BuiltinFnIdSetFnTest:
968 case BuiltinFnIdSetFnVisible:
969 case BuiltinFnIdSetFnStaticEval:
970 case BuiltinFnIdSetFnNoInline:
971 case BuiltinFnIdSetDebugSafety:
972 return false;
973 }
974
975 return false;
976}
977
978static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
979 assert(node->type == NodeTypeFnCallExpr);
980
981 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
982 CastOp cast_op = node->data.fn_call_expr.cast_op;
983 if (node->data.fn_call_expr.is_builtin) {
984 return eval_fn_call_builtin(ef, node, out_val);
985 } else if (cast_op != CastOpNoCast) {
986 TypeTableEntry *new_type = resolve_expr_type(fn_ref_expr);
987 AstNode *param_node = node->data.fn_call_expr.params.at(0);
988 TypeTableEntry *old_type = get_resolved_expr(param_node)->type_entry;
989 ConstExprValue param_val = {0};
990 if (eval_expr(ef, param_node, &param_val)) return true;
991 eval_const_expr_implicit_cast(cast_op, &param_val, old_type, out_val, new_type);
992 return false;
993 }
994
995 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
996
997 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
998 fn_ref_expr->data.field_access_expr.is_member_fn)
999 {
1000 zig_panic("TODO field access member fn");
1001 }
1002
1003 if (!fn_table_entry) {
1004 ConstExprValue fn_val = {0};
1005 if (eval_expr(ef, fn_ref_expr, &fn_val)) return true;
1006 fn_table_entry = fn_val.data.x_fn;
1007 }
1008
1009 size_t param_count = node->data.fn_call_expr.params.length;
1010 ConstExprValue *args = allocate<ConstExprValue>(param_count);
1011 for (size_t call_i = 0; call_i < param_count; call_i += 1) {
1012 AstNode *param_expr_node = node->data.fn_call_expr.params.at(call_i);
1013 ConstExprValue *param_val = &args[call_i];
1014 if (eval_expr(ef, param_expr_node, param_val)) return true;
1015 }
1016
1017 ef->root->branches_used += 1;
1018
1019 eval_fn_args(ef->root, fn_table_entry, args, out_val);
1020 return false;
1021}
1022
1023static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1024 assert(node->type == NodeTypeFieldAccessExpr);
1025
1026 AstNode *struct_expr = node->data.field_access_expr.struct_expr;
1027 TypeTableEntry *struct_type = get_resolved_expr(struct_expr)->type_entry;
1028
1029 if (struct_type->id == TypeTableEntryIdArray) {
1030 Buf *name = node->data.field_access_expr.field_name;
1031 assert(buf_eql_str(name, "len"));
1032 zig_panic("TODO field access array");
1033 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
1034 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
1035 {
1036 TypeStructField *tsf = node->data.field_access_expr.type_struct_field;
1037 assert(tsf);
1038 if (struct_type->id == TypeTableEntryIdStruct) {
1039 ConstExprValue struct_val = {0};
1040 if (eval_expr(ef, struct_expr, &struct_val)) return true;
1041 ConstExprValue *field_value = struct_val.data.x_struct.fields[tsf->src_index];
1042 *out_val = *field_value;
1043 assert(out_val->ok);
1044 } else {
1045 zig_panic("TODO field access struct");
1046 }
1047 } else if (struct_type->id == TypeTableEntryIdMetaType) {
1048 TypeTableEntry *child_type = resolve_expr_type(struct_expr);
1049 if (child_type->id == TypeTableEntryIdPureError) {
1050 *out_val = get_resolved_expr(node)->const_val;
1051 } else {
1052 zig_panic("TODO field access meta type");
1053 }
1054 } else if (struct_type->id == TypeTableEntryIdNamespace) {
1055 zig_panic("TODO field access namespace");
1056 } else {
1057 zig_unreachable();
1058 }
1059
1060 return false;
1061}
1062
1063static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1064 assert(node->type == NodeTypeForExpr);
1065
1066 AstNode *array_node = node->data.for_expr.array_expr;
1067 AstNode *elem_node = node->data.for_expr.elem_node;
1068 AstNode *index_node = node->data.for_expr.index_node;
1069 AstNode *body_node = node->data.for_expr.body;
1070
1071 TypeTableEntry *array_type = get_resolved_expr(array_node)->type_entry;
1072
1073 ConstExprValue array_val = {0};
1074 if (eval_expr(ef, array_node, &array_val)) return true;
1075
1076 assert(elem_node->type == NodeTypeSymbol);
1077 Buf *elem_var_name = elem_node->data.symbol_expr.symbol;
1078
1079 if (node->data.for_expr.elem_is_ptr) {
1080 zig_panic("TODO for elem is ptr");
1081 }
1082
1083 Buf *index_var_name = nullptr;
1084 if (index_node) {
1085 assert(index_node->type == NodeTypeSymbol);
1086 index_var_name = index_node->data.symbol_expr.symbol;
1087 }
1088
1089 uint64_t it_index = 0;
1090 uint64_t array_len;
1091 ConstExprValue **array_ptr_val;
1092 if (array_type->id == TypeTableEntryIdArray) {
1093 array_len = array_type->data.array.len;
1094 array_ptr_val = array_val.data.x_array.fields;
1095 } else if (array_type->id == TypeTableEntryIdStruct) {
1096 ConstExprValue *len_field_val = array_val.data.x_struct.fields[1];
1097 array_len = len_field_val->data.x_bignum.data.x_uint;
1098 array_ptr_val = array_val.data.x_struct.fields[0]->data.x_ptr.ptr;
1099 } else {
1100 zig_unreachable();
1101 }
1102
1103 EvalScope *my_scope = allocate<EvalScope>(1);
1104 my_scope->block_context = body_node->block_context;
1105 ef->scope_stack.append(my_scope);
1106
1107 for (; it_index < array_len; it_index += 1) {
1108 my_scope->vars.resize(0);
1109
1110 if (index_var_name) {
1111 my_scope->vars.add_one();
1112 EvalVar *index_var = &my_scope->vars.last();
1113 index_var->name = index_var_name;
1114 memset(&index_var->value, 0, sizeof(ConstExprValue));
1115 index_var->value.ok = true;
1116 bignum_init_unsigned(&index_var->value.data.x_bignum, it_index);
1117 }
1118 {
1119 my_scope->vars.add_one();
1120 EvalVar *elem_var = &my_scope->vars.last();
1121 elem_var->name = elem_var_name;
1122 elem_var->value = *array_ptr_val[it_index];
1123 }
1124
1125 ConstExprValue body_val = {0};
1126 if (eval_expr(ef, body_node, &body_val)) return true;
1127
1128 ef->root->branches_used += 1;
1129 }
1130
1131 ef->scope_stack.pop();
1132
1133 return false;
1134}
1135
1136static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1137 assert(node->type == NodeTypeArrayAccessExpr);
1138
1139 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
1140 AstNode *index_node = node->data.array_access_expr.subscript;
1141
1142 TypeTableEntry *array_type = get_resolved_expr(array_ref_node)->type_entry;
1143
1144 ConstExprValue array_val = {0};
1145 if (eval_expr(ef, array_ref_node, &array_val)) return true;
1146
1147 ConstExprValue index_val = {0};
1148 if (eval_expr(ef, index_node, &index_val)) return true;
1149 uint64_t index_int = index_val.data.x_bignum.data.x_uint;
1150
1151 if (array_type->id == TypeTableEntryIdPointer) {
1152 if (index_int >= array_val.data.x_ptr.len) {
1153 zig_panic("TODO array access pointer");
1154 }
1155 *out_val = *array_val.data.x_ptr.ptr[index_int];
1156 } else if (array_type->id == TypeTableEntryIdStruct) {
1157 assert(array_type->data.structure.is_slice);
1158
1159 ConstExprValue *len_value = array_val.data.x_struct.fields[1];
1160 uint64_t len_int = len_value->data.x_bignum.data.x_uint;
1161 if (index_int >= len_int) {
1162 zig_panic("TODO array access slice");
1163 }
1164
1165 ConstExprValue *ptr_value = array_val.data.x_struct.fields[0];
1166 *out_val = *ptr_value->data.x_ptr.ptr[index_int];
1167 } else if (array_type->id == TypeTableEntryIdArray) {
1168 uint64_t array_len = array_type->data.array.len;
1169 if (index_int >= array_len) {
1170 zig_panic("TODO array access array");
1171 }
1172 *out_val = *array_val.data.x_array.fields[index_int];
1173 } else {
1174 zig_unreachable();
1175 }
1176
1177 return false;
1178}
1179
1180static bool eval_bool_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1181 assert(node->type == NodeTypeBoolLiteral);
1182
1183 out_val->ok = true;
1184 out_val->data.x_bool = node->data.bool_literal.value;
1185
1186 return false;
1187}
1188
1189static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1190 assert(node->type == NodeTypePrefixOpExpr);
1191
1192 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
1193 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
1194
1195 ConstExprValue expr_val = {0};
1196 if (eval_expr(ef, expr_node, &expr_val)) return true;
1197
1198 TypeTableEntry *expr_type = get_resolved_expr(expr_node)->type_entry;
1199
1200 switch (prefix_op) {
1201 case PrefixOpBoolNot:
1202 *out_val = expr_val;
1203 out_val->data.x_bool = !out_val->data.x_bool;
1204 break;
1205 case PrefixOpDereference:
1206 assert(expr_type->id == TypeTableEntryIdPointer);
1207 *out_val = *expr_val.data.x_ptr.ptr[0];
1208 break;
1209 case PrefixOpAddressOf:
1210 case PrefixOpConstAddressOf:
1211 {
1212 ConstExprValue *child_val = allocate<ConstExprValue>(1);
1213 *child_val = expr_val;
1214
1215 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
1216 *ptr_val = child_val;
1217
1218 out_val->data.x_ptr.ptr = ptr_val;
1219 out_val->data.x_ptr.len = 1;
1220 out_val->ok = true;
1221 break;
1222 }
1223 case PrefixOpNegation:
1224 case PrefixOpNegationWrap:
1225 if (expr_type->id == TypeTableEntryIdInt) {
1226 assert(expr_type->data.integral.is_signed);
1227 bignum_negate(&out_val->data.x_bignum, &expr_val.data.x_bignum);
1228 out_val->ok = true;
1229 bool overflow = !bignum_fits_in_bits(&out_val->data.x_bignum,
1230 expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
1231 if (prefix_op == PrefixOpNegationWrap) {
1232 if (overflow) {
1233 out_val->data.x_bignum.is_negative = true;
1234 }
1235 } else if (overflow) {
1236 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
1237 buf_sprintf("function evaluation caused overflow"));
1238 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
1239 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
1240 return true;
1241 }
1242 } else if (expr_type->id == TypeTableEntryIdFloat) {
1243 zig_panic("TODO prefix op on floats");
1244 } else {
1245 zig_unreachable();
1246 }
1247 break;
1248 case PrefixOpBinNot:
1249 case PrefixOpMaybe:
1250 case PrefixOpError:
1251 case PrefixOpUnwrapError:
1252 case PrefixOpUnwrapMaybe:
1253 zig_panic("TODO more prefix operations");
1254 case PrefixOpInvalid:
1255 zig_unreachable();
1256 }
1257
1258 return false;
1259}
1260
1261static bool eval_var_decl_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1262 assert(node->type == NodeTypeVariableDeclaration);
1263
1264 assert(node->data.variable_declaration.expr);
1265
1266 EvalScope *my_scope = ef->scope_stack.at(ef->scope_stack.length - 1);
1267
1268 my_scope->vars.add_one();
1269 EvalVar *var = &my_scope->vars.last();
1270 var->name = node->data.variable_declaration.symbol;
1271
1272 if (eval_expr(ef, node->data.variable_declaration.expr, &var->value)) return true;
1273
1274 out_val->ok = true;
1275
1276 return false;
1277}
1278
1279static bool eval_number_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1280 assert(node->type == NodeTypeNumberLiteral);
1281 assert(!node->data.number_literal.overflow);
1282
1283 out_val->ok = true;
1284 bignum_init_bignum(&out_val->data.x_bignum, node->data.number_literal.bignum);
1285
1286 return false;
1287}
1288
1289static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1290 assert(node->type == NodeTypeCharLiteral);
1291
1292 out_val->ok = true;
1293 bignum_init_unsigned(&out_val->data.x_bignum, node->data.char_literal.value);
1294
1295 return false;
1296}
1297
1298static bool eval_while_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1299 assert(node->type == NodeTypeWhileExpr);
1300
1301 AstNode *cond_node = node->data.while_expr.condition;
1302 AstNode *body_node = node->data.while_expr.body;
1303 AstNode *continue_expr_node = node->data.while_expr.continue_expr;
1304
1305 EvalScope *my_scope = allocate<EvalScope>(1);
1306 my_scope->block_context = body_node->block_context;
1307 ef->scope_stack.append(my_scope);
1308
1309 for (;;) {
1310 my_scope->vars.resize(0);
1311
1312 ConstExprValue cond_val = {0};
1313 if (eval_expr(ef, cond_node, &cond_val)) return true;
1314
1315 if (!cond_val.data.x_bool) break;
1316
1317 ConstExprValue body_val = {0};
1318 if (eval_expr(ef, body_node, &body_val)) return true;
1319
1320 if (continue_expr_node) {
1321 ConstExprValue continue_expr_val = {0};
1322 if (eval_expr(ef, continue_expr_node, &continue_expr_val)) return true;
1323 }
1324
1325 ef->root->branches_used += 1;
1326 }
1327
1328 ef->scope_stack.pop();
1329
1330 return false;
1331}
1332
1333static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
1334 if (ef->root->branches_used > ef->root->branch_quota) {
1335 ef->root->exceeded_quota_node = node;
1336 return true;
1337 }
1338 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
1339 if (const_val->ok) {
1340 *out = *const_val;
1341 return false;
1342 }
1343 switch (node->type) {
1344 case NodeTypeBlock:
1345 return eval_block(ef, node, out);
1346 case NodeTypeReturnExpr:
1347 return eval_return(ef, node, out);
1348 case NodeTypeBinOpExpr:
1349 return eval_bin_op_expr(ef, node, out);
1350 case NodeTypeSymbol:
1351 return eval_symbol_expr(ef, node, out);
1352 case NodeTypeContainerInitExpr:
1353 return eval_container_init_expr(ef, node, out);
1354 case NodeTypeIfBoolExpr:
1355 return eval_if_bool_expr(ef, node, out);
1356 case NodeTypeFnCallExpr:
1357 return eval_fn_call_expr(ef, node, out);
1358 case NodeTypeFieldAccessExpr:
1359 return eval_field_access_expr(ef, node, out);
1360 case NodeTypeForExpr:
1361 return eval_for_expr(ef, node, out);
1362 case NodeTypeArrayAccessExpr:
1363 return eval_array_access_expr(ef, node, out);
1364 case NodeTypeBoolLiteral:
1365 return eval_bool_literal_expr(ef, node, out);
1366 case NodeTypePrefixOpExpr:
1367 return eval_prefix_op_expr(ef, node, out);
1368 case NodeTypeVariableDeclaration:
1369 return eval_var_decl_expr(ef, node, out);
1370 case NodeTypeNumberLiteral:
1371 return eval_number_literal_expr(ef, node, out);
1372 case NodeTypeCharLiteral:
1373 return eval_char_literal_expr(ef, node, out);
1374 case NodeTypeWhileExpr:
1375 return eval_while_expr(ef, node, out);
1376 case NodeTypeDefer:
1377 case NodeTypeErrorValueDecl:
1378 case NodeTypeUnwrapErrorExpr:
1379 case NodeTypeStringLiteral:
1380 case NodeTypeSliceExpr:
1381 case NodeTypeNullLiteral:
1382 case NodeTypeUndefinedLiteral:
1383 case NodeTypeZeroesLiteral:
1384 case NodeTypeThisLiteral:
1385 case NodeTypeIfVarExpr:
1386 case NodeTypeSwitchExpr:
1387 case NodeTypeSwitchProng:
1388 case NodeTypeSwitchRange:
1389 case NodeTypeLabel:
1390 case NodeTypeGoto:
1391 case NodeTypeBreak:
1392 case NodeTypeContinue:
1393 case NodeTypeContainerDecl:
1394 case NodeTypeStructField:
1395 case NodeTypeStructValueField:
1396 case NodeTypeArrayType:
1397 case NodeTypeErrorType:
1398 case NodeTypeTypeLiteral:
1399 case NodeTypeVarLiteral:
1400 zig_panic("TODO expr node");
1401 case NodeTypeRoot:
1402 case NodeTypeFnProto:
1403 case NodeTypeFnDef:
1404 case NodeTypeFnDecl:
1405 case NodeTypeUse:
1406 case NodeTypeAsmExpr:
1407 case NodeTypeParamDecl:
1408 case NodeTypeTypeDecl:
1409 zig_unreachable();
1410 }
1411 zig_unreachable();
1412}
1413
1414static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val) {
1415 AstNode *acting_proto_node;
1416 if (fn->proto_node->data.fn_proto.generic_proto_node) {
1417 acting_proto_node = fn->proto_node->data.fn_proto.generic_proto_node;
1418 } else {
1419 acting_proto_node = fn->proto_node;
1420 }
1421
1422 EvalFn ef = {0};
1423 ef.root = efr;
1424 ef.fn = fn;
1425 ef.return_expr = out_val;
1426
1427 EvalScope *root_scope = allocate<EvalScope>(1);
1428 root_scope->block_context = fn->fn_def_node->data.fn_def.body->block_context;
1429 ef.scope_stack.append(root_scope);
1430
1431 size_t param_count = acting_proto_node->data.fn_proto.params.length;
1432 for (size_t proto_i = 0; proto_i < param_count; proto_i += 1) {
1433 AstNode *decl_param_node = acting_proto_node->data.fn_proto.params.at(proto_i);
1434 assert(decl_param_node->type == NodeTypeParamDecl);
1435
1436 ConstExprValue *src_const_val = &args[proto_i];
1437 assert(src_const_val->ok);
1438
1439 root_scope->vars.add_one();
1440 EvalVar *eval_var = &root_scope->vars.last();
1441 eval_var->name = decl_param_node->data.param_decl.name;
1442 eval_var->value = *src_const_val;
1443 }
1444
1445 return eval_expr(&ef, fn->fn_def_node->data.fn_def.body, out_val);
1446}
1447
1448bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_val,
1449 size_t branch_quota, AstNode *struct_node)
1450{
1451 assert(node->type == NodeTypeFnCallExpr);
1452
1453 EvalFnRoot efr = {0};
1454 efr.codegen = g;
1455 efr.fn = fn;
1456 efr.call_node = node;
1457 efr.branch_quota = branch_quota;
1458
1459 AstNode *acting_proto_node;
1460 if (fn->proto_node->data.fn_proto.generic_proto_node) {
1461 acting_proto_node = fn->proto_node->data.fn_proto.generic_proto_node;
1462 } else {
1463 acting_proto_node = fn->proto_node;
1464 }
1465
1466 size_t call_param_count = node->data.fn_call_expr.params.length;
1467 size_t proto_param_count = acting_proto_node->data.fn_proto.params.length;
1468 ConstExprValue *args = allocate<ConstExprValue>(proto_param_count);
1469 size_t next_arg_index = 0;
1470 if (struct_node) {
1471 ConstExprValue *struct_val = &get_resolved_expr(struct_node)->const_val;
1472 assert(struct_val->ok);
1473 args[next_arg_index] = *struct_val;
1474 next_arg_index += 1;
1475 }
1476 for (size_t call_index = 0; call_index < call_param_count; call_index += 1) {
1477 AstNode *call_param_node = node->data.fn_call_expr.params.at(call_index);
1478 ConstExprValue *src_const_val = &get_resolved_expr(call_param_node)->const_val;
1479 assert(src_const_val->ok);
1480 args[next_arg_index] = *src_const_val;
1481 next_arg_index += 1;
1482 }
1483 eval_fn_args(&efr, fn, args, out_val);
1484
1485 if (efr.exceeded_quota_node) {
1486 ErrorMsg *msg = add_node_error(g, fn->fn_def_node,
1487 buf_sprintf("function evaluation exceeded %zu branches", efr.branch_quota));
1488
1489 add_error_note(g, msg, efr.call_node, buf_sprintf("called from here"));
1490 add_error_note(g, msg, efr.exceeded_quota_node, buf_sprintf("quota exceeded here"));
1491 return true;
1492 }
1493
1494 if (efr.abort) {
1495 return true;
1496 }
1497
1498 assert(out_val->ok);
1499 return false;
1500}
1501
src/eval.hpp-3
...@@ -10,9 +10,6 @@...@@ -10,9 +10,6 @@
1010
11#include "all_types.hpp"11#include "all_types.hpp"
1212
13bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_val, size_t branch_quota,
14 AstNode *struct_node);
15
16bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);13bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);
17int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,14int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
18 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val);15 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val);