Skip to content

Commit

Permalink
Interpreter: handle local variable type declaration (#12239)
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite authored Jul 12, 2022
1 parent f0ca89b commit 0953fda
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 25 deletions.
7 changes: 7 additions & 0 deletions spec/compiler/interpreter/primitives_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ describe Crystal::Repl::Interpreter do
x
CODE
end

it "interprets local variable declaration (#12229)" do
interpret(<<-CODE).should eq(1)
a : Int32 = 1
a
CODE
end
end

context "conversion" do
Expand Down
62 changes: 37 additions & 25 deletions src/compiler/crystal/interpreter/compiler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -566,27 +566,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor
target = node.target
case target
when Var
request_value(node.value)

# If it's the case of `x = a = 1` then we need to preserve the value
# of 1 in the stack because it will be assigned to `x` too
# (set_local removes the value from the stack)
if @wants_value
dup(aligned_sizeof_type(node.value), node: nil)
end

if target.special_var?
# We need to assign through the special var pointer
var = lookup_local_var("#{target.name}*")
var_type = var.type.as(PointerInstanceType).element_type

upcast node.value, node.value.type, var_type

get_local var.index, sizeof(Void*), node: node
pointer_set inner_sizeof_type(var_type), node: node
else
assign_to_var(target.name, node.value.type, node: node)
end
compile_assign_to_var(node, target, node.value)
when InstanceVar
if inside_method?
request_value(node.value)
Expand Down Expand Up @@ -689,6 +669,30 @@ class Crystal::Repl::Compiler < Crystal::Visitor
false
end

def compile_assign_to_var(node : ASTNode, target : ASTNode, value : ASTNode)
request_value(value)

# If it's the case of `x = a = 1` then we need to preserve the value
# of 1 in the stack because it will be assigned to `x` too
# (set_local removes the value from the stack)
if @wants_value
dup(aligned_sizeof_type(value), node: nil)
end

if target.special_var?
# We need to assign through the special var pointer
var = lookup_local_var("#{target.name}*")
var_type = var.type.as(PointerInstanceType).element_type

upcast value, value.type, var_type

get_local var.index, sizeof(Void*), node: node
pointer_set inner_sizeof_type(var_type), node: node
else
assign_to_var(target.name, value.type, node: node)
end
end

private def assign_to_var(name : String, value_type : Type, *, node : ASTNode?)
var = lookup_local_var_or_closured_var(name)

Expand All @@ -703,6 +707,18 @@ class Crystal::Repl::Compiler < Crystal::Visitor
end
end

def visit(node : TypeDeclaration)
var = node.var
return false unless var.is_a?(Var)

value = node.value
return false unless value

compile_assign_to_var(node, var, value)

false
end

def visit(node : Var)
return false unless @wants_value

Expand Down Expand Up @@ -2986,10 +3002,6 @@ class Crystal::Repl::Compiler < Crystal::Visitor
false
end

def visit(node : TypeDeclaration)
false
end

def visit(node : Alias)
false
end
Expand Down

0 comments on commit 0953fda

Please sign in to comment.