diff --git a/lib/ast/node.rb b/lib/ast/node.rb index 511c70d..bf3c6c3 100644 --- a/lib/ast/node.rb +++ b/lib/ast/node.rb @@ -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 + # 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}" 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 diff --git a/test/test_ast.rb b/test/test_ast.rb index e05fa4d..3f76ef3 100644 --- a/test/test_ast.rb +++ b/test/test_ast.rb @@ -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 @@ -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 @@ -201,14 +203,12 @@ 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 @@ -216,13 +216,8 @@ def @processor.on_arglist(node) 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