Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Reference.pre_initialize in the interpreter #14968

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions spec/primitives/reference_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ describe "Primitives: reference" do
end
end

# TODO: implement in the interpreter
pending_interpreted describe: ".pre_initialize" do
describe ".pre_initialize" do
it "doesn't fail on complex ivar initializer if value is discarded (#14325)" do
bar_buffer = GC.malloc(instance_sizeof(Outer))
Outer.pre_initialize(bar_buffer)
Expand All @@ -55,7 +54,12 @@ describe "Primitives: reference" do
it "sets type ID" do
foo_buffer = GC.malloc(instance_sizeof(Foo))
base = Foo.pre_initialize(foo_buffer).as(Base)
base.crystal_type_id.should eq(Foo.crystal_instance_type_id)
base.should be_a(Foo)
base.as(typeof(Foo.crystal_instance_type_id)*).value.should eq(Foo.crystal_instance_type_id)
{% unless flag?(:interpreted) %}
# FIXME: `Object#crystal_type_id` is incorrect for virtual types in the interpreter (#14967)
base.crystal_type_id.should eq(Foo.crystal_instance_type_id)
{% end %}
end

it "runs inline instance initializers" do
Expand Down Expand Up @@ -89,7 +93,7 @@ describe "Primitives: reference" do
end
end

pending_interpreted describe: ".unsafe_construct" do
describe ".unsafe_construct" do
it "constructs an object in-place" do
foo_buffer = GC.malloc(instance_sizeof(Foo))
foo = Foo.unsafe_construct(foo_buffer, 123_i64)
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/crystal/interpreter/instructions.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,16 @@ require "./repl"
ptr
end,
},
reset_class: {
operands: [size : Int32, type_id : Int32],
pop_values: [pointer : Pointer(UInt8)],
push: true,
code: begin
pointer.clear(size)
pointer.as(Int32*).value = type_id
pointer
end,
},
put_metaclass: {
operands: [size : Int32, union_type : Bool],
push: true,
Expand Down
24 changes: 24 additions & 0 deletions src/compiler/crystal/interpreter/primitives.cr
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,30 @@ class Crystal::Repl::Compiler
pop(sizeof(Pointer(Void)), node: nil)
end
end
when "pre_initialize"
type =
if obj
discard_value(obj)
obj.type.instance_type
else
scope.instance_type
end

accept_call_members(node)

dup sizeof(Pointer(Void)), node: nil
reset_class(aligned_instance_sizeof_type(type), type_id(type), node: node)

initializer_compiled_defs = @context.type_instance_var_initializers(type)
unless initializer_compiled_defs.empty?
initializer_compiled_defs.size.times do
dup sizeof(Pointer(Void)), node: nil
end

initializer_compiled_defs.each do |compiled_def|
call compiled_def, node: nil
end
end
when "tuple_indexer_known_index"
unless @wants_value
accept_call_members(node)
Expand Down
Loading