From 46e2b80c8620030177ea5d42e6a6cd797d7dfc94 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 4 Oct 2022 11:49:56 -0300 Subject: [PATCH 1/2] Interpreter: implement variable autocast --- spec/compiler/interpreter/autocast_spec.cr | 33 +++++++++++++++++++ src/compiler/crystal/interpreter/compiler.cr | 11 +++++-- .../crystal/interpreter/primitives.cr | 2 +- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/spec/compiler/interpreter/autocast_spec.cr b/spec/compiler/interpreter/autocast_spec.cr index 9efe9fda3582..0f192f64eeea 100644 --- a/spec/compiler/interpreter/autocast_spec.cr +++ b/spec/compiler/interpreter/autocast_spec.cr @@ -102,5 +102,38 @@ describe Crystal::Repl::Interpreter do foo.color.value CODE end + + it "autocasts integer var to integer (#12560)" do + interpret(<<-CODE).should eq(1) + def foo(x : Int64) + x + end + + x = 1 + foo(x) + CODE + end + + it "autocasts integer var to float (#12560)" do + interpret(<<-CODE).should eq(1) + def foo(x : Float64) + x + end + + x = 1 + foo(x) + CODE + end + + it "autocasts float32 var to float64 (#12560)" do + interpret(<<-CODE).should eq(1) + def foo(x : Float64) + x + end + + x = 1.0_f32 + foo(x) + CODE + end end end diff --git a/src/compiler/crystal/interpreter/compiler.cr b/src/compiler/crystal/interpreter/compiler.cr index 39296b49ad6b..fc4fd789be98 100644 --- a/src/compiler/crystal/interpreter/compiler.cr +++ b/src/compiler/crystal/interpreter/compiler.cr @@ -2341,9 +2341,14 @@ class Crystal::Repl::Compiler < Crystal::Visitor request_value(arg) - # We first cast the argument to the def's arg type, - # which is the external methods' type. - downcast arg, arg_type, target_def_arg_type + # Check number autocast but for variables + if arg_type != target_def_arg_type && arg_type.is_a?(IntegerType | FloatType) && target_def_arg_type.is_a?(IntegerType | FloatType) + primitive_convert(arg, arg_type, target_def_arg_type, checked: false) + else + # We first cast the argument to the def's arg type, + # which is the external methods' type. + downcast arg, arg_type, target_def_arg_type + end # Then we need to cast the argument to the target_def variable # corresponding to the argument. If for example we have this: diff --git a/src/compiler/crystal/interpreter/primitives.cr b/src/compiler/crystal/interpreter/primitives.cr index 3980ff1d060a..34cc22b2dbab 100644 --- a/src/compiler/crystal/interpreter/primitives.cr +++ b/src/compiler/crystal/interpreter/primitives.cr @@ -646,7 +646,7 @@ class Crystal::Repl::Compiler to_kind = integer_or_float_kind(to_type) unless from_kind && to_kind - node.raise "BUG: missing handling of unchecked_convert for #{from_type} (#{node.name})" + node.raise "BUG: missing handling of unchecked_convert for #{from_type} (#{node})" end primitive_convert(node, from_kind, to_kind, checked: checked) From 516d6caa7ab420b18f700af54dc62147848e4a46 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Tue, 4 Oct 2022 12:08:51 -0300 Subject: [PATCH 2/2] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller --- spec/compiler/interpreter/autocast_spec.cr | 4 ++-- src/compiler/crystal/interpreter/compiler.cr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/compiler/interpreter/autocast_spec.cr b/spec/compiler/interpreter/autocast_spec.cr index 0f192f64eeea..0aa9e93c250c 100644 --- a/spec/compiler/interpreter/autocast_spec.cr +++ b/spec/compiler/interpreter/autocast_spec.cr @@ -109,7 +109,7 @@ describe Crystal::Repl::Interpreter do x end - x = 1 + x = 1_i32 foo(x) CODE end @@ -120,7 +120,7 @@ describe Crystal::Repl::Interpreter do x end - x = 1 + x = 1_i32 foo(x) CODE end diff --git a/src/compiler/crystal/interpreter/compiler.cr b/src/compiler/crystal/interpreter/compiler.cr index fc4fd789be98..1ec8d115b170 100644 --- a/src/compiler/crystal/interpreter/compiler.cr +++ b/src/compiler/crystal/interpreter/compiler.cr @@ -2341,7 +2341,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor request_value(arg) - # Check number autocast but for variables + # Check number autocast but for non-literals if arg_type != target_def_arg_type && arg_type.is_a?(IntegerType | FloatType) && target_def_arg_type.is_a?(IntegerType | FloatType) primitive_convert(arg, arg_type, target_def_arg_type, checked: false) else