Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/ast/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -188,18 +188,21 @@ def to_a
end

# Converts `self` to a pretty-printed s-expression.
# Using the Sexp module the output can be used as ruby code to
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obsolete comment

# generate the expressions (handy for tests)
#
# @param [Integer] indent Base indentation level.
# @return [String]
def to_sexp(indent=0)
indented = " " * indent
sexp = "#{indented}(#{fancy_type}"
sexp = "#{indented}s(:#{@type}"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er. This is not at all what I described in #6 (comment). The convention in Ruby is for inspect to output something you can run to get the object back (hence it should print the s(:... version of code, and to_s to output a readable representation (which already happens in to_sexp). There was no need to change to_sexp...


first_node_child = children.index do |child|
child.is_a?(Node) || child.is_a?(Array)
end || children.count

children.each_with_index do |child, idx|
sexp << ", "
if child.is_a?(Node) && idx >= first_node_child
sexp << "\n#{child.to_sexp(indent + 1)}"
else
Expand Down
41 changes: 18 additions & 23 deletions test/test_ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,18 @@ class MetaNode < AST::Node
end

it 'should format to_sexp correctly' do
AST::Node.new(:a, [ :sym, [ 1, 2 ] ]).to_sexp.should.equal '(a :sym [1, 2])'
AST::Node.new(:a, [ :sym, @node ]).to_sexp.should.equal "(a :sym\n (node 0 1))"
AST::Node.new(:a, [ :sym, [ 1, 2 ] ]).to_sexp.should.equal 's(:a, :sym, [1, 2])'
AST::Node.new(:a, [ :sym, @node ]).to_sexp.should.equal "s(:a, :sym, \n s(:node, 0, 1))"
AST::Node.new(:a, [ :sym,
AST::Node.new(:b, [ @node, @node ])
]).to_sexp.should.equal "(a :sym\n (b\n (node 0 1)\n (node 0 1)))"
]).to_sexp.should.equal "s(:a, :sym, \n s(:b, \n s(:node, 0, 1), \n s(:node, 0, 1)))"
end

it 'should output equivalnet ruby code' do
simple_node = AST::Node.new(:a, [ :sym, [ 1, 2 ] ])
eval(simple_node.to_sexp).should.equal simple_node
complex_node = s(:a , :sym, s(:b, s(:node, 0, 1), s(:node, 0, 1)))
eval(complex_node.to_sexp).should.equal complex_node
end

it 'should return self in to_ast' do
Expand Down Expand Up @@ -138,11 +145,6 @@ def obj.children
describe AST::Processor do
extend AST::Sexp

def have_sexp(text)
text = text.lines.map { |line| line.sub /^ +\|(.+)/, '\1' }.join.rstrip
lambda { |ast| ast.to_sexp == text }
end

class MockProcessor < AST::Processor
attr_reader :counts

Expand Down Expand Up @@ -201,28 +203,21 @@ def @processor.on_arglist(node)
node.updated(:new_fancy_arglist)
end

@processor.process(@ast).should have_sexp(<<-SEXP)
|(root
| (def :func
| (new-fancy-arglist :foo :bar)
| (body
| (invoke :puts "Hello world")))
| (invoke :func))
SEXP
@processor.process(@ast).should == s(:root,
s(:def, :func,
s(:new_fancy_arglist, :foo, :bar),
s(:body,
s(:invoke, :puts, "Hello world"))),
s(:invoke, :func) )
end

it 'should build sexps' do
s(:add,
s(:integer, 1),
s(:multiply,
s(:integer, 2),
s(:integer, 3))).should have_sexp(<<-SEXP)
|(add
| (integer 1)
| (multiply
| (integer 2)
| (integer 3)))
SEXP
s(:integer, 3))).inspect.should ==
"s(:add, \n s(:integer, 1), \n s(:multiply, \n s(:integer, 2), \n s(:integer, 3)))"
end

it 'should return nil if passed nil' do
Expand Down