Skip to content

Commit

Permalink
Add Crystal::Repl::Value#runtime_type (#14156)
Browse files Browse the repository at this point in the history
Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl>
  • Loading branch information
bcardiff and Sija committed Sep 3, 2024
1 parent 598931c commit 6ee4eb9
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
49 changes: 49 additions & 0 deletions spec/compiler/crystal/tools/repl_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,53 @@ describe Crystal::Repl do
success_value(repl.parse_and_interpret("def foo; 1 + 2; end")).value.should eq(nil)
success_value(repl.parse_and_interpret("foo")).value.should eq(3)
end

describe "can return static and runtime type information for" do
it "Non Union" do
repl = Crystal::Repl.new
repl.prelude = "primitives"
repl.load_prelude

repl_value = success_value(repl.parse_and_interpret("1"))
repl_value.type.to_s.should eq("Int32")
repl_value.runtime_type.to_s.should eq("Int32")
end

it "MixedUnionType" do
repl = Crystal::Repl.new
repl.prelude = "primitives"
repl.load_prelude

repl_value = success_value(repl.parse_and_interpret("1 || \"a\""))
repl_value.type.to_s.should eq("(Int32 | String)")
repl_value.runtime_type.to_s.should eq("Int32")
end

it "UnionType" do
repl = Crystal::Repl.new
repl.prelude = "primitives"
repl.load_prelude

repl_value = success_value(repl.parse_and_interpret("true || 1"))
repl_value.type.to_s.should eq("(Bool | Int32)")
repl_value.runtime_type.to_s.should eq("Bool")
end

it "VirtualType" do
repl = Crystal::Repl.new
repl.prelude = "primitives"
repl.load_prelude

repl.parse_and_interpret <<-CRYSTAL
class Foo
end
class Bar < Foo
end
CRYSTAL
repl_value = success_value(repl.parse_and_interpret("Bar.new || Foo.new"))
repl_value.type.to_s.should eq("Foo+") # Maybe should Foo to match typeof
repl_value.runtime_type.to_s.should eq("Bar")
end
end
end
2 changes: 2 additions & 0 deletions src/compiler/crystal/interpreter/primitives.cr
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class Crystal::Repl::Compiler

pointer_add(inner_sizeof_type(element_type), node: node)
when "class"
# Should match Crystal::Repl::Value#runtime_type
# in src/compiler/crystal/interpreter/value.cr
obj = obj.not_nil!
type = obj.type.remove_indirection

Expand Down
15 changes: 15 additions & 0 deletions src/compiler/crystal/interpreter/value.cr
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ struct Crystal::Repl::Value
end
end

def runtime_type : Crystal::Type
# Should match Crystal::Repl::Compiler#visit_primitive "class" case
# in src/compiler/crystal/interpreter/primitives.cr
case type
when Crystal::UnionType
type_id = @pointer.as(Int32*).value
context.type_from_id(type_id)
when Crystal::VirtualType
type_id = @pointer.as(Void**).value.as(Int32*).value
context.type_from_id(type_id)
else
type
end
end

# Copies the contents of this value to another pointer.
def copy_to(pointer : Pointer(UInt8))
@pointer.copy_to(pointer, context.inner_sizeof_type(@type))
Expand Down

0 comments on commit 6ee4eb9

Please sign in to comment.