Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 31693b5aa877
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 13d566b9cdea
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Feb 8, 2017

  1. Fixed #3945: missing location for debug info for new with custom allo…

    …cate
    Ary Borenszweig committed Feb 8, 2017
    Copy the full SHA
    ac6b628 View commit details
  2. Fixed #3995: Syntax error when calling absolutely scoped class with s…

    …horthand notation
    Ary Borenszweig committed Feb 8, 2017
    Copy the full SHA
    13d566b View commit details
Showing with 43 additions and 20 deletions.
  1. +15 −0 spec/compiler/codegen/debug_spec.cr
  2. +3 −0 spec/compiler/parser/parser_spec.cr
  3. +19 −19 src/compiler/crystal/semantic/new.cr
  4. +6 −1 src/compiler/crystal/syntax/parser.cr
15 changes: 15 additions & 0 deletions spec/compiler/codegen/debug_spec.cr
Original file line number Diff line number Diff line change
@@ -63,4 +63,19 @@ describe "Code gen: debug" do
end
), debug: Crystal::Debug::All)
end

it "codegens correct debug info for new with custom allocate (#3945)" do
codegen(%(
class Foo
def initialize
end
def self.allocate
Pointer(UInt8).malloc(1_u64).as(self)
end
end
Foo.new
), debug: Crystal::Debug::All)
end
end
3 changes: 3 additions & 0 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
@@ -469,6 +469,9 @@ describe "Parser" do
it_parses %(Foo({"foo bar": X})), Generic.new("Foo".path, [Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("foo bar", "X".path)])] of ASTNode)
it_parses %(Foo({"foo": X, "bar": Y})), Generic.new("Foo".path, [Generic.new(Path.global("NamedTuple"), [] of ASTNode, named_args: [NamedArgument.new("foo", "X".path), NamedArgument.new("bar", "Y".path)])] of ASTNode)

it_parses %(Foo{"x" => "y"}), HashLiteral.new([HashLiteral::Entry.new("x".string, "y".string)], name: "Foo".path)
it_parses %(::Foo{"x" => "y"}), HashLiteral.new([HashLiteral::Entry.new("x".string, "y".string)], name: Path.global("Foo"))

it_parses "Foo(*T)", Generic.new("Foo".path, ["T".path.splat] of ASTNode)

it_parses "Foo(X, sizeof(Int32))", Generic.new("Foo".path, ["X".path, SizeOf.new("Int32".path)] of ASTNode)
38 changes: 19 additions & 19 deletions src/compiler/crystal/semantic/new.cr
Original file line number Diff line number Diff line change
@@ -149,14 +149,14 @@ module Crystal
def fill_body_from_initialize(instance_type)
if instance_type.is_a?(GenericClassType)
generic_type_args = instance_type.type_vars.map_with_index do |type_var, i|
arg = Path.new(type_var).as(ASTNode)
arg = Splat.new(arg) if instance_type.splat_index == i
arg = Path.new(type_var).as(ASTNode).at(self)
arg = Splat.new(arg).at(self) if instance_type.splat_index == i
arg
end
new_generic = Generic.new(Path.new(instance_type.name), generic_type_args)
alloc = Call.new(new_generic, "allocate")
alloc = Call.new(new_generic, "allocate").at(self)
else
alloc = Call.new(nil, "allocate")
alloc = Call.new(nil, "allocate").at(self)
end

# This creates:
@@ -178,44 +178,44 @@ module Crystal
# Check if the argument has to be passed as a named argument
if splat_index && i > splat_index
named_args ||= [] of NamedArgument
named_args << NamedArgument.new(arg.name, Var.new(arg.name))
named_args << NamedArgument.new(arg.name, Var.new(arg.name).at(self)).at(self)
else
new_var = Var.new(arg.name)
new_var = Splat.new(new_var) if i == splat_index
new_var = Var.new(arg.name).at(self)
new_var = Splat.new(new_var).at(self) if i == splat_index
new_vars << new_var
end
end

# Make sure to forward the double splat argument
if double_splat = self.double_splat
new_vars << DoubleSplat.new(Var.new(double_splat.name))
new_vars << DoubleSplat.new(Var.new(double_splat.name).at(self)).at(self)
end

assign = Assign.new(obj.clone, alloc)
assign = Assign.new(obj.clone, alloc).at(self)
init = Call.new(obj.clone, "initialize", new_vars, named_args: named_args).at(self)

# If the initialize yields, call it with a block
# that yields those arguments.
if block_args_count = self.yields
block_args = Array.new(block_args_count) { |i| Var.new("_arg#{i}") }
vars = Array.new(block_args_count) { |i| Var.new("_arg#{i}").as(ASTNode) }
init.block = Block.new(block_args, Yield.new(vars))
vars = Array.new(block_args_count) { |i| Var.new("_arg#{i}").at(self).as(ASTNode) }
init.block = Block.new(block_args, Yield.new(vars).at(self)).at(self)
end

exps = Array(ASTNode).new(4)
exps << assign
exps << init
exps << If.new(RespondsTo.new(obj.clone, "finalize"),
Call.new(Path.global("GC"), "add_finalizer", obj.clone).at(self))
exps << If.new(RespondsTo.new(obj.clone, "finalize").at(self),
Call.new(Path.global("GC").at(self), "add_finalizer", obj.clone).at(self))
exps << obj

# Forward block argument if any
if uses_block_arg?
block_arg = self.block_arg.not_nil!
init.block_arg = Var.new(block_arg.name)
init.block_arg = Var.new(block_arg.name).at(self)
end

self.body = Expressions.from(exps)
self.body = Expressions.from(exps).at(self)
end

def self.argless_new(instance_type)
@@ -228,14 +228,14 @@ module Crystal
# GC.add_finalizer x if x.responds_to? :finalize
# x
# end
var = Var.new("x")
var = Var.new("x").at(loc)
alloc = Call.new(nil, "allocate").at(loc)
assign = Assign.new(var, alloc)
assign = Assign.new(var, alloc).at(loc)

call = Call.new(Path.global("GC"), "add_finalizer", var.clone).at(loc)
call = Call.new(Path.global("GC").at(loc), "add_finalizer", var.clone).at(loc)
exps = Array(ASTNode).new(3)
exps << assign
exps << If.new(RespondsTo.new(var.clone, "finalize"), call)
exps << If.new(RespondsTo.new(var.clone, "finalize").at(loc), call).at(loc)
exps << var.clone

a_def = Def.new("new", body: exps).at(loc)
7 changes: 6 additions & 1 deletion src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
@@ -1122,6 +1122,10 @@ module Crystal

def parse_ident_or_literal
ident = parse_ident
parse_custom_literal ident
end

def parse_custom_literal(ident)
skip_space

if @token.type == :"{"
@@ -4097,10 +4101,11 @@ module Crystal
when :IDENT
set_visibility parse_var_or_call global: true
when :CONST
parse_ident_after_colons location,
ident = parse_ident_after_colons location,
global: true,
allow_type_vars: true,
parse_nilable: true
parse_custom_literal ident
else
unexpected_token
end