Skip to content

Commit

Permalink
Showing 6 changed files with 43 additions and 6 deletions.
5 changes: 5 additions & 0 deletions spec/compiler/parser/parser_spec.cr
Original file line number Diff line number Diff line change
@@ -791,6 +791,11 @@ describe "Parser" do
it_parses "foo.nil?( )", IsA.new("foo".call, Path.global("Nil"), nil_check: true)

it_parses "foo &.nil?", Call.new(nil, "foo", block: Block.new([Var.new("__arg0")], IsA.new(Var.new("__arg0"), Path.global("Nil"), nil_check: true)))
it_parses "foo &.baz.qux do\nend", Call.new(nil, "foo",
block: Block.new(["__arg0".var],
Call.new(Call.new("__arg0".var, "baz"), "qux", block: Block.new)
)
)

it_parses "/foo/", regex("foo")
it_parses "/foo/i", regex("foo", Regex::Options::IGNORE_CASE)
14 changes: 14 additions & 0 deletions spec/compiler/type_inference/macro_spec.cr
Original file line number Diff line number Diff line change
@@ -884,4 +884,18 @@ describe "Type inference: macro" do
Foo.bar
)) { int32 }
end

it "can override macro (#2773)" do
assert_type(%(
macro foo
1
end
macro foo
'a'
end
foo
)) { char }
end
end
11 changes: 11 additions & 0 deletions src/compiler/crystal/semantic/restrictions.cr
Original file line number Diff line number Diff line change
@@ -149,6 +149,17 @@ module Crystal
end
end

class Macro
def overrides?(other : Macro)
# For now we consider that a macro overrides another macro
# if it has the same number of arguments, splat index and
# named arguments.
args.size == other.args.size &&
splat_index == other.splat_index &&
!!double_splat == !!other.double_splat
end
end

class Path
def restriction_of?(other : Path, owner)
return true if self == other
10 changes: 6 additions & 4 deletions src/compiler/crystal/syntax/parser.cr
Original file line number Diff line number Diff line change
@@ -1464,10 +1464,10 @@ module Crystal
call.args << exp
end
else
# At this point we want to attach the "do" to the next call,
# so we set this var to true to make the parser think the call
# has parentheses and so a "do" must be attached to it
call = preserve_stop_on_do { parse_var_or_call(force_call: true).at(location) }
# At this point we want to attach the "do" to the next call
old_stop_on_do = @stop_on_do
@stop_on_do = false
call = parse_var_or_call(force_call: true).at(location)

if call.is_a?(Call)
call.obj = obj
@@ -1502,6 +1502,8 @@ module Crystal
call.args << exp
end
end

@stop_on_do = old_stop_on_do
end

block = Block.new([Var.new(block_arg_name)], call).at(location)
7 changes: 6 additions & 1 deletion src/compiler/crystal/types.cr
Original file line number Diff line number Diff line change
@@ -699,7 +699,12 @@ module Crystal

macros = (@macros ||= {} of String => Array(Macro))
array = (macros[a_def.name] ||= [] of Macro)
array.push a_def
index = array.index { |existing_macro| a_def.overrides?(existing_macro) }
if index
array[index] = a_def
else
array.push a_def
end
end

def add_hook(kind, a_def, args_size = 0)
2 changes: 1 addition & 1 deletion src/fiber.cr
Original file line number Diff line number Diff line change
@@ -98,7 +98,7 @@ class Fiber
io.puts "Unhandled exception:"
ex.inspect_with_backtrace io
end
LibC.write(2, pointerof(msg).as(Void*), msg.bytesize)
LibC.write(2, msg, msg.bytesize)
ensure
@@stack_pool << @stack

0 comments on commit ecf8487

Please sign in to comment.