Skip to content

Commit

Permalink
Implement Reference.pre_initialize in the interpreter (#14968)
Browse files Browse the repository at this point in the history
  • Loading branch information
HertzDevil authored Sep 5, 2024
1 parent 256c555 commit 05c5eaa
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
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

0 comments on commit 05c5eaa

Please sign in to comment.