add also calls on classes and more tests for that

This commit is contained in:
Torsten Ruger 2014-05-31 17:58:26 +03:00
parent 4038bd331a
commit 86431120d5
8 changed files with 93 additions and 38 deletions

View File

@ -2,10 +2,12 @@ module Ast
# assignment, like operators are really function calls # assignment, like operators are really function calls
class CallSiteExpression < Expression class CallSiteExpression < Expression
attr_reader :name, :args attr_reader :name, :args , :receiver
def initialize name, args
@name , @args = name.to_sym , args def initialize name, args , receiver = Ast::NameExpression.new("self")
@name , @args , @receiver = name.to_sym , args , receiver
end end
def compile context , into def compile context , into
params = args.collect{ |a| a.compile(context, into) } params = args.collect{ |a| a.compile(context, into) }
#TOOD, this needs dynamic resolution #TOOD, this needs dynamic resolution
@ -23,13 +25,13 @@ module Ast
def inspect def inspect
self.class.name + ".new(" + name.inspect + ", ["+ self.class.name + ".new(" + name.inspect + ", ["+
args.collect{|m| m.inspect }.join( ",") +"] )" args.collect{|m| m.inspect }.join( ",") + "] ," + receiver.inspect + ")"
end end
def to_s def to_s
"#{name}(" + args.join(",") + ")" "#{name}(" + args.join(",") + ")"
end end
def attributes def attributes
[:name , :args] [:name , :args , :receiver]
end end
end end

View File

@ -9,7 +9,8 @@ module Parser
space? >> right_parenthesis space? >> right_parenthesis
} }
rule(:call_site) { (name.as(:receiver) >> str(".")).repeat(0,1) >> name.as(:call_site) >> argument_list >> comment.maybe} rule(:call_site) { ((module_name|name).as(:receiver) >> str(".")).maybe >> #possibly qualified
name.as(:call_site) >> argument_list >> comment.maybe}
end end

View File

@ -23,7 +23,11 @@ module Parser
rule( :call_site => simple(:call_site), rule( :call_site => simple(:call_site),
:argument_list => sequence(:argument_list)) do :argument_list => sequence(:argument_list)) do
Ast::CallSiteExpression.new(call_site.name, argument_list) Ast::CallSiteExpression.new(call_site.name, argument_list )
end
rule( :receiver => simple(:receiver) , :call_site => simple(:call_site),
:argument_list => sequence(:argument_list)) do
Ast::CallSiteExpression.new(call_site.name, argument_list , receiver)
end end
rule(:if => simple(:if), :conditional => simple(:conditional), rule(:if => simple(:if), :conditional => simple(:conditional),

View File

@ -12,6 +12,27 @@ class TestCallSite < MiniTest::Test
@parser = @parser.call_site @parser = @parser.call_site
end end
def test_single_self
@string_input = 'self.foo(42)'
@parse_output = {:receiver=>{:name=>"self"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new 'foo', [Ast::IntegerExpression.new(42)]
@parser = @parser.call_site
end
def test_single_name
@string_input = 'my_my.foo(42)'
@parse_output = {:receiver=>{:name=>"my_my"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::NameExpression.new("my_my"))
@parser = @parser.call_site
end
def test_single_class
@string_input = 'Object.foo(42)'
@parse_output = {:receiver=>{:module_name=>"Object"}, :call_site=>{:name=>"foo"}, :argument_list=>[{:argument=>{:integer=>"42"}}]}
@transform_output = Ast::CallSiteExpression.new(:foo, [Ast::IntegerExpression.new(42)] ,Ast::ModuleName.new("Object"))
@parser = @parser.call_site
end
def test_call_site_multi def test_call_site_multi
@string_input = 'baz(42, foo)' @string_input = 'baz(42, foo)'
@parse_output = {:call_site => {:name => 'baz' }, @parse_output = {:call_site => {:name => 'baz' },
@ -52,4 +73,18 @@ class TestCallSite < MiniTest::Test
@parser = @parser.call_site @parser = @parser.call_site
end end
def test_call_chaining_name
@string_input = 'puts(name.putint(4), a)'
@parse_output = {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:receiver=>{:name=>"name"}, :call_site=>{:name=>"putint"}, :argument_list=>[{:argument=>{:integer=>"4"}}]}}, {:argument=>{:name=>"a"}}]}
@transform_output = Ast::CallSiteExpression.new(:puts, [Ast::CallSiteExpression.new(:putint, [Ast::IntegerExpression.new(4)] ,Ast::NameExpression.new("name")),Ast::NameExpression.new("a")] ,Ast::NameExpression.new("self"))
@parser = @parser.call_site
end
def test_call_chaining_class
@string_input = 'Class.new(self.get(4))'
@parse_output = {:receiver=>{:module_name=>"Class"}, :call_site=>{:name=>"new"}, :argument_list=>[{:argument=>{:receiver=>{:name=>"self"}, :call_site=>{:name=>"get"}, :argument_list=>[{:argument=>{:integer=>"4"}}]}}]}
@transform_output = Ast::CallSiteExpression.new(:new, [Ast::CallSiteExpression.new(:get, [Ast::IntegerExpression.new(4)] ,Ast::NameExpression.new("self"))] ,Ast::ModuleName.new("Class"))
@parser = @parser.call_site
end
end end

View File

@ -20,12 +20,22 @@ else
end end
HERE HERE
@string_input = "if #{cond} " + input.chop! @string_input = "if #{cond} " + input.chop!
@parse_output = {:if=>"if", :conditional=>{:integer=>"0"}, @parse_output = {:if=>"if", :conditional=>{:integer=>"0"}, :if_true=>{:expressions=>[{:integer=>"42"}], :else=>"else"}, :if_false=>{:expressions=>[{:integer=>"667"}], :end=>"end"}}
:if_true=>{:expressions=>[{:integer=>"42"}], :else=>"else"}, @transform_output = Ast::IfExpression.new(Ast::IntegerExpression.new(0), [Ast::IntegerExpression.new(42)],[Ast::IntegerExpression.new(667)] )
:if_false=>{:expressions=>[{:integer=>"667"}], :end=>"end"}} @parser = @parser.conditional
@transform_output = Ast::IfExpression.new( Ast::IntegerExpression.new(0), end
[Ast::IntegerExpression.new(42)], [Ast::IntegerExpression.new(667)])
def test_conditional_with_calls
@string_input = <<HERE
if(3 > var)
Object.initialize(3)
else
var.new(33)
end
HERE
@string_input.chop!
@parse_output = {:if=>"if", :conditional=>{:l=>{:integer=>"3"}, :o=>"> ", :r=>{:name=>"var"}}, :if_true=>{:expressions=>[{:receiver=>{:module_name=>"Object"}, :call_site=>{:name=>"initialize"}, :argument_list=>[{:argument=>{:integer=>"3"}}]}], :else=>"else"}, :if_false=>{:expressions=>[{:receiver=>{:name=>"var"}, :call_site=>{:name=>"new"}, :argument_list=>[{:argument=>{:integer=>"33"}}]}], :end=>"end"}}
@transform_output = Ast::IfExpression.new(Ast::OperatorExpression.new(">", Ast::IntegerExpression.new(3),Ast::NameExpression.new("var")), [Ast::CallSiteExpression.new(:initialize, [Ast::IntegerExpression.new(3)] ,Ast::ModuleName.new("Object"))],[Ast::CallSiteExpression.new(:new, [Ast::IntegerExpression.new(33)] ,Ast::NameExpression.new("var"))] )
@parser = @parser.conditional @parser = @parser.conditional
end end
end end

View File

@ -70,6 +70,7 @@ HERE
@transform_output = Ast::ModuleExpression.new(:Soho ,[Ast::CallSiteExpression.new(:ofthen, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new("var")] ), Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n"),Ast::NameExpression.new("m")] , [Ast::IntegerExpression.new(44)] )] ) @transform_output = Ast::ModuleExpression.new(:Soho ,[Ast::CallSiteExpression.new(:ofthen, [Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(3),Ast::IntegerExpression.new(4)),Ast::NameExpression.new("var")] ), Ast::FunctionExpression.new(:ofthen, [Ast::NameExpression.new("n"),Ast::NameExpression.new("m")] , [Ast::IntegerExpression.new(44)] )] )
@parser = @parser.module_definition @parser = @parser.module_definition
end end
def test_module_class def test_module_class
@string_input = <<HERE @string_input = <<HERE
module Foo module Foo

View File

@ -102,6 +102,17 @@ HERE
@transform_output = [Ast::ModuleExpression.new(:FooBo ,[Ast::ClassExpression.new(:Bar ,[Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(5),Ast::NameExpression.new("foo")))] )] )] @transform_output = [Ast::ModuleExpression.new(:FooBo ,[Ast::ClassExpression.new(:Bar ,[Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::OperatorExpression.new("+", Ast::IntegerExpression.new(5),Ast::NameExpression.new("foo")))] )] )]
end end
def test_class_method
@string_input = <<HERE
class FooBo
Bar.call(35)
end
HERE
@parse_output = [{:module_name=>"FooBo", :class_expressions=>[{:receiver=>{:module_name=>"Bar"}, :call_site=>{:name=>"call"}, :argument_list=>[{:argument=>{:integer=>"35"}}]}], :end=>"end"}]
@transform_output = [Ast::ClassExpression.new(:FooBo ,[Ast::CallSiteExpression.new(:call, [Ast::IntegerExpression.new(35)] ,Ast::ModuleName.new("Bar"))] )]
end
end end

View File

@ -12,15 +12,21 @@ while(1) do
end end
HERE HERE
@string_input.chop! @string_input.chop!
@parse_output = {:while=>"while", @parse_output = {:while=>"while", :while_cond=>{:integer=>"1"}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}], :end=>"end"}}
:while_cond=>{:integer=>"1"}, @transform_output = Ast::WhileExpression.new(Ast::IntegerExpression.new(1), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("b")] ,Ast::NameExpression.new("self"))] )
:do=>"do", @parser = @parser.while_do
:body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, end
{:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}], :end=>"end"}}
@transform_output = Ast::WhileExpression.new( def test_while_method
Ast::IntegerExpression.new(1), @string_input = <<HERE
[Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), while(1) do
Ast::CallSiteExpression.new("puts", [Ast::NameExpression.new("b")] )] ) tmp = String.new()
tmp.puts(i)
end
HERE
@string_input.chop!
@parse_output = {:while=>"while", :while_cond=>{:integer=>"1"}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:receiver=>{:module_name=>"String"}, :call_site=>{:name=>"new"}, :argument_list=>[]}}, {:receiver=>{:name=>"tmp"}, :call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"i"}}]}], :end=>"end"}}
@transform_output = Ast::WhileExpression.new(Ast::IntegerExpression.new(1), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::CallSiteExpression.new(:new, [] ,Ast::ModuleName.new("String"))), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("i")] ,Ast::NameExpression.new("tmp"))] )
@parser = @parser.while_do @parser = @parser.while_do
end end
@ -35,23 +41,8 @@ while( n > 1) do
end end
HERE HERE
@string_input.chop! @string_input.chop!
@parse_output = {:while=>"while", @parse_output = {:while=>"while", :while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"1"}}, :do=>"do", :body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}}, {:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}}, {:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}}, {:call_site=>{:name=>"puts"}, :argument_list=>[{:argument=>{:name=>"b"}}]}, {:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}], :end=>"end"}}
:while_cond=>{:l=>{:name=>"n"}, :o=>"> ", :r=>{:integer=>"1"}}, @transform_output = Ast::WhileExpression.new(Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)), [Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new(:puts, [Ast::NameExpression.new("b")] ,Ast::NameExpression.new("self")), Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )
:do=>"do",
:body=>{:expressions=>[{:l=>{:name=>"tmp"}, :o=>"= ", :r=>{:name=>"a"}},
{:l=>{:name=>"a"}, :o=>"= ", :r=>{:name=>"b"}},
{:l=>{:name=>"b"}, :o=>"= ", :r=>{:l=>{:name=>"tmp"}, :o=>"+ ", :r=>{:name=>"b"}}},
{:call_site=>{:name=>"puts"},
:argument_list=>[{:argument=>{:name=>"b"}}]},
{:l=>{:name=>"n"}, :o=>"= ", :r=>{:l=>{:name=>"n"}, :o=>"- ", :r=>{:integer=>"1"}}}],
:end=>"end"}}
@transform_output = Ast::WhileExpression.new(
Ast::OperatorExpression.new(">", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)),
[Ast::OperatorExpression.new("=", Ast::NameExpression.new("tmp"),Ast::NameExpression.new("a")),
Ast::OperatorExpression.new("=", Ast::NameExpression.new("a"),Ast::NameExpression.new("b")),
Ast::OperatorExpression.new("=", Ast::NameExpression.new("b"),Ast::OperatorExpression.new("+", Ast::NameExpression.new("tmp"),
Ast::NameExpression.new("b"))), Ast::CallSiteExpression.new("puts", [Ast::NameExpression.new("b")] ),
Ast::OperatorExpression.new("=", Ast::NameExpression.new("n"),Ast::OperatorExpression.new("-", Ast::NameExpression.new("n"),Ast::IntegerExpression.new(1)))] )
@parser = @parser.while_do @parser = @parser.while_do
end end
end end