Skip to content

Commit

Permalink
Added macro methods to access a node's location. Related to #3017
Browse files Browse the repository at this point in the history
  • Loading branch information
Ary Borenszweig committed Jul 20, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 514778f commit cf24ccf
Showing 4 changed files with 81 additions and 1 deletion.
22 changes: 22 additions & 0 deletions spec/compiler/macro/macro_methods_spec.cr
Original file line number Diff line number Diff line change
@@ -2,6 +2,28 @@ require "../../spec_helper"

describe "macro methods" do
describe "node methods" do
describe "location" do
it "filename" do
assert_macro "x", "{{x.filename}}", ["hello".string.tap { |n| n.location = Location.new(1, 2, "foo.cr") }] of ASTNode, %("foo.cr")
end

it "line_number" do
assert_macro "x", "{{x.line_number}}", ["hello".string.tap { |n| n.location = Location.new(1, 2, "foo.cr") }] of ASTNode, %(1)
end

it "column number" do
assert_macro "x", "{{x.column_number}}", ["hello".string.tap { |n| n.location = Location.new(1, 2, "foo.cr") }] of ASTNode, %(2)
end

it "end line_number" do
assert_macro "x", "{{x.end_line_number}}", ["hello".string.tap { |n| n.end_location = Location.new(1, 2, "foo.cr") }] of ASTNode, %(1)
end

it "end column number" do
assert_macro "x", "{{x.end_column_number}}", ["hello".string.tap { |n| n.end_location = Location.new(1, 2, "foo.cr") }] of ASTNode, %(2)
end
end

describe "stringify" do
it "expands macro with stringify call on string" do
assert_macro "x", "{{x.stringify}}", ["hello".string] of ASTNode, "\"\\\"hello\\\"\""
33 changes: 33 additions & 0 deletions src/compiler/crystal/macros.cr
Original file line number Diff line number Diff line change
@@ -75,6 +75,39 @@ module Crystal::Macros
def run(filename, *args) : MacroId
end

# Returns the filename where this node is located.
# Might return nil if the location is not known.
def filename : StringLiteral | NilLiteral
end

# Returns the line number where this node begins.
# Might return nil if the location is not known.
#
# The first line number in a file is 1.
def line_number : StringLiteral | NilLiteral
end

# Returns the column number where this node begins.
# Might return nil if the location is not known.
#
# The first column number in a line is 1.
def column_number : StringLiteral | NilLiteral
end

# Returns the line number where this node ends.
# Might return nil if the location is not known.
#
# The first line number in a file is 1.
def end_line_number : StringLiteral | NilLiteral
end

# Returns the column number where this node ends.
# Might return nil if the location is not known.
#
# The first column number in a line is 1.
def end_column_number : StringLiteral | NilLiteral
end

# This is the base class of all AST nodes. This methods are
# available to all AST nodes.
abstract class ASTNode
25 changes: 25 additions & 0 deletions src/compiler/crystal/macros/methods.cr
Original file line number Diff line number Diff line change
@@ -200,6 +200,31 @@ module Crystal
interpret_one_arg_method(method, args) do |arg|
raise arg.to_s
end
when "filename"
interpret_argless_method("filename", args) do
filename = location.try &.original_filename
filename ? StringLiteral.new(filename) : NilLiteral.new
end
when "line_number"
interpret_argless_method("line_number", args) do
line_number = location.try &.original_location.try &.line_number
line_number ? NumberLiteral.new(line_number) : NilLiteral.new
end
when "column_number"
interpret_argless_method("column_number", args) do
column_number = location.try &.original_location.try &.column_number
column_number ? NumberLiteral.new(column_number) : NilLiteral.new
end
when "end_line_number"
interpret_argless_method("end_line_number", args) do
line_number = end_location.try &.original_location.try &.line_number
line_number ? NumberLiteral.new(line_number) : NilLiteral.new
end
when "end_column_number"
interpret_argless_method("end_column_number", args) do
column_number = end_location.try &.original_location.try &.column_number
column_number ? NumberLiteral.new(column_number) : NilLiteral.new
end
when "=="
interpret_one_arg_method(method, args) do |arg|
BoolLiteral.new(self == arg)
2 changes: 1 addition & 1 deletion src/compiler/crystal/syntax/location.cr
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ module Crystal
end

def original_filename
original_location.try &.filename
original_location.try &.filename.as?(String)
end

def between?(min, max)

0 comments on commit cf24ccf

Please sign in to comment.