test/pt_testcase.rb in ParseTree-1.5.0 vs test/pt_testcase.rb in ParseTree-1.6.0

- old
+ new

@@ -1,15 +1,32 @@ require 'test/unit/testcase' -require 'sexp_processor' # for deep_clone FIX -require 'typed_sexp' +require 'sexp_processor' # for deep_clone require 'unique' -# TODO: str -> char * in ansi c -# TODO: add tests that mix types up to fuck up RubyC type checker +class Examples + attr_reader :reader + attr_writer :writer -class R2CTestCase < Test::Unit::TestCase + def a_method; 1+1; end + alias an_alias a_method + def self.bmethod_maker + define_method(:bmethod_added) do |x| + x + 1 + end + end + + def self.dmethod_maker + define_method :dmethod_added, self.method(:bmethod_maker) + end if RUBY_VERSION < "1.9" + + bmethod_maker + dmethod_maker if RUBY_VERSION < "1.9" +end + +class ParseTreeTestCase < Test::Unit::TestCase + attr_accessor :processor # to be defined by subclass def self.testcase_order; @@testcase_order; end def self.testcases; @@testcases; end @@ -17,1302 +34,886 @@ super @processor = nil Unique.reset end - @@testcase_order = %w(Ruby ParseTree Rewriter TypeChecker CRewriter RubyToAnsiC RubyToRubyC) + @@testcase_order = %w(Ruby ParseTree) @@testcases = { + + "alias" => { + "Ruby" => "class X\n alias :y :x\nend", + "ParseTree" => [:class, :X, nil, + [:scope, [:alias, [:lit, :y], [:lit, :x]]]], + "Ruby2Ruby" => "class X\n alias_method :y, :x\n \nend", # FIX dbl \n + }, - "accessor" => { - "Ruby" => "attr_reader :accessor", - "ParseTree" => [:defn, :accessor, [:ivar, :@accessor]], - "Rewriter" => s(:defn, :accessor, s(:args), - s(:scope, - s(:block, s(:return, s(:ivar, :@accessor))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToAnsiC" => :skip, - "RubyToRubyC" => :skip, + "and" => { + "Ruby" => "(a and b)", + "ParseTree" => [:and, [:vcall, :a], [:vcall, :b]], }, - "accessor_equals" => { - "Ruby" => "attr_writer :accessor", - "ParseTree" => [:defn, :accessor=, [:attrset, :@accessor]], - "Rewriter" => s(:defn, - :accessor=, - s(:args, :arg), - s(:scope, - s(:block, - s(:return, - s(:iasgn, :@accessor, s(:lvar, :arg)))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + "args" => { + "Ruby" => "def x(a, b = 42, \*c, &d)\n p(a, b, c, d)\nend", + "ParseTree" => [:defn, :x, + [:scope, + [:block, + [:args, :a, :b, "*c".intern, # s->e + [:block, [:lasgn, :b, [:lit, 42]]]], + [:block_arg, :d], + [:fcall, :p, + [:array, [:lvar, :a], [:lvar, :b], + [:lvar, :c], [:lvar, :d]]]]]] }, + + "argscat" => { + "Ruby" => "a = b, c, *d", + "ParseTree" => [:lasgn, :a, + [:svalue, + [:argscat, + [:array, [:vcall, :b], [:vcall, :c]], + [:vcall, :d]]]], + }, - "defn_bbegin" => { - "Ruby" => "def bbegin() - begin - 1 + 1 - rescue SyntaxError - e1 = $! - 2 - rescue Exception - e2 = $! - 3 - else - 4end - ensure - 5 -end", - "ParseTree" => [:defn, :bbegin, - [:scope, - [:block, - [:args], - [:begin, - [:ensure, - [:rescue, - [:call, [:lit, 1], :+, [:array, [:lit, 1]]], - [:resbody, - [:array, [:const, :SyntaxError]], - [:block, [:lasgn, :e1, [:gvar, :$!]], [:lit, 2]], - [:resbody, - [:array, [:const, :Exception]], - [:block, [:lasgn, :e2, [:gvar, :$!]], [:lit, 3]]]], - [:lit, 4]], - [:lit, 5]]]]]], - "Rewriter" => s(:defn, :bbegin, - s(:args), - s(:scope, - s(:block, - s(:begin, - s(:ensure, - s(:rescue, - s(:call, s(:lit, 1), :+, s(:arglist, s(:lit, 1))), - s(:resbody, - s(:array, s(:const, :SyntaxError)), - s(:block, s(:lasgn, :e1, s(:gvar, :$!)), - s(:lit, 2)), - s(:resbody, - s(:array, s(:const, :Exception)), - s(:block, s(:lasgn, :e2, s(:gvar, :$!)), - s(:lit, 3)))), - s(:lit, 4)), - s(:lit, 5)))))), - "TypeChecker" => t(:defn, :bbegin, - t(:args), - t(:scope, - t(:block, - t(:begin, - t(:ensure, - t(:rescue, - t(:call, - t(:lit, 1, Type.long), - :+, - t(:arglist, t(:lit, 1, Type.long)), Type.long), - t(:resbody, - t(:array, t(:const, :SyntaxError, Type.fucked)), - t(:block, - t(:lasgn, :e1, t(:gvar, :$!, Type.unknown), - Type.unknown), - t(:lit, 2, Type.long), Type.unknown), - t(:resbody, - t(:array, t(:const, :Exception, Type.fucked)), - t(:block, - t(:lasgn, :e2, t(:gvar, :$!, Type.unknown), - Type.unknown), - t(:lit, 3, Type.long), Type.unknown), - Type.unknown), Type.long), - t(:lit, 4, Type.long), Type.long), - t(:lit, 5, Type.long))), Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.void)), - "CRewriter" => :same, - "RubyToRubyC" => :unsupported, - "RubyToAnsiC" => :unsupported, + "argspush" => { + "Ruby" => "a[*b] = c", + "ParseTree" => [:attrasgn, + [:vcall, :a], + :[]=, + [:argspush, [:splat, [:vcall, :b]], [:vcall, :c]]], + "Ruby2Ruby" => "a.[]=(*b, c)" # HACK until we can get things ironed out }, - "bools" => { - "Ruby" => "def bools(arg1) - if (arg1.nil?) - return false - else - return true - end -end", - "ParseTree" => [:defn, :bools, - [:scope, - [:block, - [:args, :arg1], - [:if, - [:call, [:lvar, :arg1], "nil?".intern], # emacs is freakin' - [:return, [:false]], - [:return, [:true]]]]]], - "Rewriter" => s(:defn, :bools, - s(:args, :arg1), - s(:scope, - s(:block, - s(:if, - s(:call, - s(:lvar, :arg1), - :nil?, - nil), - s(:return, s(:false)), - s(:return, s(:true)))))), - # TODO: why does return false have type void? - "TypeChecker" => t(:defn, :bools, - t(:args, t(:arg1, Type.value)), - t(:scope, - t(:block, - t(:if, - t(:call, - t(:lvar, :arg1, Type.value), - :nil?, - nil, - Type.bool), - t(:return, - t(:false, Type.bool), - Type.void), - t(:return, - t(:true, Type.bool), - Type.void), - Type.void), - Type.unknown), - Type.void), - Type.function(Type.unknown, [Type.value], Type.bool)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE\nrrc_c_bools(VALUE self, VALUE arg1) {\nif (NIL_P(arg1)) {\nreturn Qfalse;\n} else {\nreturn Qtrue;\n}\n}", - "RubyToAnsiC" => "bool\nbools(void * arg1) {\nif (arg1) {\nreturn 0;\n} else {\nreturn 1;\n}\n}", + "array" => { + "Ruby" => "[1, :b, \"c\"]", + "ParseTree" => [:array, [:lit, 1], [:lit, :b], [:str, "c"]], }, -# TODO: move all call tests here - "call_arglist" => { - "Ruby" => "puts(42)", - "ParseTree" => [:fcall, :puts, [:array, [:lit, 42]]], - "Rewriter" => s(:call, nil, :puts, s(:arglist, s(:lit, 42))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + "attrasgn" => { + "Ruby" => "y = 0\n42.method=(y)\n", + "ParseTree" => [:block, + [:lasgn, :y, [:lit, 0]], + [:attrasgn, [:lit, 42], :method=, [:array, [:lvar, :y]]]], }, - "call_attrasgn" => { - "Ruby" => "42.method=(y)", - "ParseTree" => [:attrasgn, [:lit, 42], :method=, [:array, [:lvar, :y]]], - "Rewriter" => s(:call, s(:lit, 42), :method=, s(:arglist, s(:lvar, :y))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + "attrset" => { + "Ruby" => [Examples, :writer=], + "ParseTree" => [:defn, :writer=, [:attrset, :@writer]], + "Ruby2Ruby" => "attr_writer :writer" }, + + "back_ref" => { + "Ruby" => "[$&, $`, $', $+]", + "ParseTree" => [:array, + [:back_ref, :&], + [:back_ref, "`".intern], # symbol was fucking up emacs + [:back_ref, "'".intern], # s->e + [:back_ref, :+]], + }, + + "begin" => { + "Ruby" => "begin\n (1 + 1)\nend", + "ParseTree" => [:begin, [:call, [:lit, 1], :+, [:array, [:lit, 1]]]], + }, - "call_self" => { + "block_pass" => { + "Ruby" => "a(&b)", + "ParseTree" => [:block_pass, [:vcall, :b], [:fcall, :a]], + }, + + "bmethod" => { + "Ruby" => [Examples, :bmethod_added], + "ParseTree" => [:defn, + :bmethod_added, + [:bmethod, + [:dasgn_curr, :x], + [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]], + "Ruby2Ruby" => "def bmethod_added(x)\n (x + 1)\nend" + }, + + "break" => { + "Ruby" => "loop do\n if true then\n break\n end\nend", + "ParseTree" => [:iter, + [:fcall, :loop], nil, [:if, [:true], [:break], nil]], + }, + + "break_arg" => { + "Ruby" => "loop do\n if true then\n break 42\n end\nend", + "ParseTree" => [:iter, + [:fcall, :loop], nil, + [:if, [:true], [:break, [:lit, 42]], nil]], + }, + + "call" => { "Ruby" => "self.method", "ParseTree" => [:call, [:self], :method], - "Rewriter" => s(:call, s(:lvar, :self), :method, nil), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, }, - "case_stmt" => { - "Ruby" => " -def case_stmt() - var = 2 - result = \"\" - case var - when 1 - puts(\"something\") - result = \"red\" - when 2, 3 - result = \"yellow\" - when 4 - else - result = \"green\" - end - case result - when \"red\" - var = 1 - when \"yellow\" - var = 2 - when \"green\" - var = 3 - else - end - return result -end", - "ParseTree" => [:defn, :case_stmt, - [:scope, - [:block, - [:args], - [:lasgn, :var, [:lit, 2]], - [:lasgn, :result, [:str, ""]], - [:case, - [:lvar, :var], - [:when, - [:array, [:lit, 1]], - [:block, - [:fcall, :puts, [:array, [:str, "something"]]], - [:lasgn, :result, [:str, "red"]]]], - [:when, - [:array, [:lit, 2], [:lit, 3]], - [:lasgn, :result, [:str, "yellow"]]], - [:when, [:array, [:lit, 4]], nil], - [:lasgn, :result, [:str, "green"]]], - [:case, - [:lvar, :result], - [:when, [:array, [:str, "red"]], [:lasgn, :var, [:lit, 1]]], - [:when, [:array, [:str, "yellow"]], [:lasgn, :var, [:lit, 2]]], - [:when, [:array, [:str, "green"]], [:lasgn, :var, [:lit, 3]]], - nil], - [:return, [:lvar, :result]]]]], - "Rewriter" => s(:defn, :case_stmt, - s(:args), - s(:scope, - s(:block, - s(:lasgn, :var, s(:lit, 2)), - s(:lasgn, :result, s(:str, "")), - s(:if, - s(:call, - s(:lvar, :var), - :===, - s(:arglist, s(:lit, 1))), - s(:block, - s(:call, - nil, - :puts, - s(:arglist, s(:str, "something"))), - s(:lasgn, :result, s(:str, "red"))), - s(:if, - s(:or, - s(:call, - s(:lvar, :var), - :===, - s(:arglist, s(:lit, 2))), - s(:call, - s(:lvar, :var), - :===, - s(:arglist, s(:lit, 3)))), - s(:lasgn, :result, s(:str, "yellow")), - s(:if, - s(:call, - s(:lvar, :var), - :===, - s(:arglist, s(:lit, 4))), - nil, - s(:lasgn, :result, s(:str, "green"))))), - s(:if, - s(:call, - s(:lvar, :result), - :===, - s(:arglist, s(:str, "red"))), - s(:lasgn, :var, s(:lit, 1)), - s(:if, - s(:call, - s(:lvar, :result), - :===, - s(:arglist, s(:str, "yellow"))), - s(:lasgn, :var, s(:lit, 2)), - s(:if, - s(:call, - s(:lvar, :result), - :===, - s(:arglist, s(:str, "green"))), - s(:lasgn, :var, s(:lit, 3)), - nil))), - s(:return, s(:lvar, :result))))), - "TypeChecker" => t(:defn, :case_stmt, - t(:args), - t(:scope, - t(:block, - t(:lasgn, - :var, - t(:lit, 2, Type.long), - Type.long), - t(:lasgn, - :result, - t(:str, "", Type.str), - Type.str), - t(:if, - t(:call, - t(:lvar, :var, Type.long), - :case_equal_long, - t(:arglist, t(:lit, 1, Type.long)), - Type.bool), - t(:block, - t(:call, - nil, - :puts, - t(:arglist, - t(:str, "something", Type.str)), - Type.void), - t(:lasgn, - :result, - t(:str, "red", Type.str), - Type.str), - Type.str), - t(:if, - t(:or, - t(:call, - t(:lvar, :var, Type.long), - :case_equal_long, - t(:arglist, t(:lit, 2, Type.long)), - Type.bool), - t(:call, - t(:lvar, :var, Type.long), - :case_equal_long, - t(:arglist, t(:lit, 3, Type.long)), - Type.bool), - Type.bool), - t(:lasgn, - :result, - t(:str, "yellow", Type.str), - Type.str), - t(:if, - t(:call, - t(:lvar, :var, Type.long), - :case_equal_long, - t(:arglist, t(:lit, 4, Type.long)), - Type.bool), - nil, - t(:lasgn, - :result, - t(:str, "green", Type.str), - Type.str), - Type.str), - Type.str), - Type.str), - t(:if, - t(:call, - t(:lvar, :result, Type.str), - :case_equal_str, - t(:arglist, t(:str, "red", Type.str)), - Type.bool), - t(:lasgn, :var, t(:lit, 1, Type.long), Type.long), - t(:if, - t(:call, - t(:lvar, :result, Type.str), - :case_equal_str, - t(:arglist, t(:str, "yellow", Type.str)), - Type.bool), - t(:lasgn, :var, t(:lit, 2, Type.long), Type.long), - t(:if, - t(:call, - t(:lvar, :result, Type.str), - :case_equal_str, - t(:arglist, - t(:str, "green", Type.str)), - Type.bool), - t(:lasgn, - :var, - t(:lit, 3, Type.long), - Type.long), - nil, - Type.long), - Type.long), - Type.long), - t(:return, - t(:lvar, :result, Type.str), - Type.void), - Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.str)), - "CRewriter" => :same, -# HACK: I don't like the semis after the if blocks, but it is a compromise right now - "RubyToRubyC" => "static VALUE -rrc_c_case_stmt(VALUE self) { -VALUE result; -VALUE var; -var = LONG2NUM(2); -result = rb_str_new2(\"\"); -if (rb_funcall(var, rb_intern(\"===\"), 1, LONG2NUM(1))) { -rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"something\")); -result = rb_str_new2(\"red\"); -} else { -if (rb_funcall(var, rb_intern(\"===\"), 1, LONG2NUM(2)) || rb_funcall(var, rb_intern(\"===\"), 1, LONG2NUM(3))) { -result = rb_str_new2(\"yellow\"); -} else { -if (rb_funcall(var, rb_intern(\"===\"), 1, LONG2NUM(4))) { -; -} else { -result = rb_str_new2(\"green\"); -} -} -}; -if (rb_funcall(result, rb_intern(\"===\"), 1, rb_str_new2(\"red\"))) { -var = LONG2NUM(1); -} else { -if (rb_funcall(result, rb_intern(\"===\"), 1, rb_str_new2(\"yellow\"))) { -var = LONG2NUM(2); -} else { -if (rb_funcall(result, rb_intern(\"===\"), 1, rb_str_new2(\"green\"))) { -var = LONG2NUM(3); -} -} -}; -return result; -}", - "RubyToAnsiC" => "str -case_stmt() { -str result; -long var; -var = 2; -result = \"\"; -if (case_equal_long(var, 1)) { -puts(\"something\"); -result = \"red\"; -} else { -if (case_equal_long(var, 2) || case_equal_long(var, 3)) { -result = \"yellow\"; -} else { -if (case_equal_long(var, 4)) { -; -} else { -result = \"green\"; -} -} -}; -if (case_equal_str(result, \"red\")) { -var = 1; -} else { -if (case_equal_str(result, \"yellow\")) { -var = 2; -} else { -if (case_equal_str(result, \"green\")) { -var = 3; -} -} -}; -return result; -}", + "call_arglist" => { + "Ruby" => "puts(42)", + "ParseTree" => [:fcall, :puts, [:array, [:lit, 42]]], }, + "case" => { + "Ruby" => "var = 2\nresult = \"\"\ncase var\nwhen 1 then\n puts(\"something\")\n result = \"red\"\nwhen 2, 3 then\n result = \"yellow\"\nwhen 4 then\n # do nothing\nelse\n result = \"green\"\nend\ncase result\nwhen \"red\" then\n var = 1\nwhen \"yellow\" then\n var = 2\nwhen \"green\" then\n var = 3\nelse\n # do nothing\nend\n", + "ParseTree" => [:block, + [:lasgn, :var, [:lit, 2]], + [:lasgn, :result, [:str, ""]], + [:case, + [:lvar, :var], + [:when, + [:array, [:lit, 1]], + [:block, + [:fcall, :puts, [:array, [:str, "something"]]], + [:lasgn, :result, [:str, "red"]]]], + [:when, + [:array, [:lit, 2], [:lit, 3]], + [:lasgn, :result, [:str, "yellow"]]], + [:when, [:array, [:lit, 4]], nil], + [:lasgn, :result, [:str, "green"]]], + [:case, + [:lvar, :result], + [:when, [:array, [:str, "red"]], + [:lasgn, :var, [:lit, 1]]], + [:when, [:array, [:str, "yellow"]], + [:lasgn, :var, [:lit, 2]]], + [:when, [:array, [:str, "green"]], + [:lasgn, :var, [:lit, 3]]], + nil]] + }, + + "cdecl" => { + "Ruby" => "X = 42", + "ParseTree" => [:cdecl, :X, [:lit, 42]], + }, + + "class" => { + "Ruby" => "class X < Array\n def blah\n puts(\"hello\")\n end\n \nend", + "ParseTree" => [:class, + :X, + [:const, :Array], + [:scope, + [:defn, + :blah, + [:scope, + [:block, + [:args], + [:fcall, :puts, [:array, [:str, "hello"]]]]]]]], + }, + + "class_obj" => { + "Ruby" => "class X\n def blah\n puts(\"hello\")\n end\n \nend", + "ParseTree" => [:class, + :X, + nil, + [:scope, + [:defn, + :blah, + [:scope, + [:block, + [:args], + [:fcall, :puts, [:array, [:str, "hello"]]]]]]]], + }, + + "colon2" => { + "Ruby" => "X::Y", + "ParseTree" => [:colon2, [:const, :X], :Y], + }, + + "colon3" => { + "Ruby" => "::X", + "ParseTree" => [:colon3, :X], + }, + "conditional1" => { - "Ruby" => "if (42 == 0)\n return 1\n\nend", - "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]], [:return, [:lit, 1]], nil], - "Rewriter" => s(:if, s(:call, s(:lit, 42), :==, s(:arglist, s(:lit, 0))), s(:return, s(:lit, 1)), nil), - "TypeChecker" => t(:if, - t(:call, t(:lit, 42, Type.long), :==, - t(:arglist, t(:lit, 0, Type.long)), - Type.bool), - t(:return, t(:lit, 1, Type.long), Type.void), - nil, - Type.void), - "CRewriter" => t(:if, - t(:call, t(:lit, 42, Type.long), :==, - t(:arglist, t(:lit, 0, Type.long)), - Type.bool), - t(:return, t(:lit, 1, Type.long), Type.void), - nil, - Type.void), - "RubyToRubyC" => "if (rb_funcall(LONG2NUM(42), rb_intern(\"==\"), 1, LONG2NUM(0))) {\nreturn LONG2NUM(1);\n}", - "RubyToAnsiC" => "if (42 == 0) {\nreturn 1;\n}", + "Ruby" => "if (42 == 0) then\n return 1\nend", + "ParseTree" => [:if, + [:call, [:lit, 42], :==, [:array, [:lit, 0]]], + [:return, [:lit, 1]], + nil], }, "conditional2" => { - "Ruby" => "unless (42 == 0)\n return 2\nend", - "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]], nil, [:return, [:lit, 2]]], - "Rewriter" => s(:if, - s(:call, s(:lit, 42), - :==, s(:arglist, s(:lit, 0))), - nil, - s(:return, s(:lit, 2))), - "TypeChecker" => t(:if, - t(:call, - t(:lit, 42, Type.long), - :==, - t(:arglist, - t(:lit, 0, Type.long)), - Type.bool), - nil, - t(:return, t(:lit, 2, Type.long), Type.void), - Type.void), - "CRewriter" => :same, - "RubyToRubyC" => "if (rb_funcall(LONG2NUM(42), rb_intern(\"==\"), 1, LONG2NUM(0))) {\n;\n} else {\nreturn LONG2NUM(2);\n}", - "RubyToAnsiC" => "if (42 == 0) {\n;\n} else {\nreturn 2;\n}", + "Ruby" => "unless (42 == 0) then\n return 2\nend", + "ParseTree" => [:if, + [:call, [:lit, 42], :==, [:array, [:lit, 0]]], + nil, + [:return, [:lit, 2]]], }, "conditional3" => { - "Ruby" => "if (42 == 0)\n return 3\nelse\n return 4\nend", + "Ruby" => "if (42 == 0) then\n return 3\nelse\n return 4\nend", "ParseTree" => [:if, [:call, [:lit, 42], :==, [:array, [:lit, 0]]], - [:return, [:lit, 3]], - [:return, [:lit, 4]]], - "Rewriter" => s(:if, - s(:call, - s(:lit, 42), - :==, - s(:arglist, s(:lit, 0))), - s(:return, s(:lit, 3)), - s(:return, s(:lit, 4))), - "TypeChecker" => t(:if, - t(:call, - t(:lit, 42, Type.long), - :==, - t(:arglist, - t(:lit, 0, Type.long)), - Type.bool), - t(:return, - t(:lit, 3, Type.long), - - Type.void), - t(:return, - t(:lit, 4, Type.long), - Type.void), - Type.void), - "CRewriter" => :same, - "RubyToRubyC" => "if (rb_funcall(LONG2NUM(42), rb_intern(\"==\"), 1, LONG2NUM(0))) {\nreturn LONG2NUM(3);\n} else {\nreturn LONG2NUM(4);\n}", - "RubyToAnsiC" => "if (42 == 0) {\nreturn 3;\n} else {\nreturn 4;\n}", + [:return, [:lit, 3]], + [:return, [:lit, 4]]], }, "conditional4" => { - "Ruby" => "if (42 == 0) - return 2 -else - if (42 < 0) - return 3 - else - return 4 - end -end", + "Ruby" => "if (42 == 0) then\n return 2\nelsif (42 < 0) then\n return 3\nelse\n return 4\nend", "ParseTree" => [:if, - [:call, [:lit, 42], :==, [:array, [:lit, 0]]], - [:return, [:lit, 2]], - [:if, - [:call, [:lit, 42], :<, [:array, [:lit, 0]]], - [:return, [:lit, 3]], - [:return, [:lit, 4]]]], - "Rewriter" => s(:if, - s(:call, - s(:lit, 42), - :==, - s(:arglist, s(:lit, 0))), - s(:return, s(:lit, 2)), - s(:if, - s(:call, - s(:lit, 42), - :<, - s(:arglist, s(:lit, 0))), - s(:return, s(:lit, 3)), - s(:return, s(:lit, 4)))), - "TypeChecker" => t(:if, - t(:call, - t(:lit, 42, Type.long), - :==, - t(:arglist, - t(:lit, 0, Type.long)), - Type.bool), - t(:return, - t(:lit, 2, Type.long), - Type.void), - t(:if, - t(:call, - t(:lit, 42, Type.long), - :<, - t(:arglist, - t(:lit, 0, Type.long)), - Type.bool), - t(:return, - t(:lit, 3, Type.long), - Type.void), - t(:return, - t(:lit, 4, Type.long), - Type.void), - Type.void), - Type.void), - "CRewriter" => :same, - "RubyToRubyC" => "if (rb_funcall(LONG2NUM(42), rb_intern(\"==\"), 1, LONG2NUM(0))) {\nreturn LONG2NUM(2);\n} else {\nif (rb_funcall(LONG2NUM(42), rb_intern(\"<\"), 1, LONG2NUM(0))) {\nreturn LONG2NUM(3);\n} else {\nreturn LONG2NUM(4);\n}\n}", - "RubyToAnsiC" => "if (42 == 0) {\nreturn 2;\n} else {\nif (42 < 0) {\nreturn 3;\n} else {\nreturn 4;\n}\n}", + [:call, [:lit, 42], :==, [:array, [:lit, 0]]], + [:return, [:lit, 2]], + [:if, + [:call, [:lit, 42], :<, [:array, [:lit, 0]]], + [:return, [:lit, 3]], + [:return, [:lit, 4]]]], }, - "defn_bmethod_added" => { - "Ruby" => "def bmethod_added(x)\n x + 1\nend", - "ParseTree" => [:defn, :bmethod_added, - [:bmethod, - [:dasgn_curr, :x], - [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]], - "Rewriter" => s(:defn, - :bmethod_added, - s(:args, :x), - s(:scope, - s(:block, - s(:call, s(:lvar, :x), :+, s(:arglist, s(:lit, 1)))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + "const" => { + "Ruby" => "X", + "ParseTree" => [:const, :X], }, - "defn_empty" => { - "Ruby" => "def empty()\n nil\nend", - "ParseTree" => [:defn, :empty, [:scope, [:block, [:args], [:nil]]]], - "Rewriter" => s(:defn, :empty, - s(:args), s(:scope, s(:block, s(:nil)))), - "TypeChecker" => t(:defn, :empty, - t(:args), - t(:scope, - t(:block, - t(:nil, Type.value), - Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.void)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE\nrrc_c_empty(VALUE self) {\nQnil;\n}", - "RubyToAnsiC" => "void\nempty() {\nNULL;\n}", + "cvar" => { + "Ruby" => "@@x", + "ParseTree" => [:cvar, :@@x], }, - "defn_zarray" => { - "Ruby" => "def empty()\n a = []\n return a\nend", - "ParseTree" => [:defn, :empty, [:scope, [:block, [:args], [:lasgn, :a, [:zarray]], [:return, [:lvar, :a]]]]], - "Rewriter" => s(:defn, - :empty, - s(:args), - s(:scope, s(:block, s(:lasgn, :a, s(:array)), s(:return, s(:lvar, :a))))), - "TypeChecker" => t(:defn, - :empty, - t(:args), - t(:scope, - t(:block, - t(:lasgn, :a, t(:array), Type.unknown_list), - t(:return, - t(:lvar, - :a, Type.unknown_list), Type.void), - Type.unknown), Type.void), - Type.function(Type.unknown, [], Type.unknown_list)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE\nrrc_c_empty(VALUE self) {\nVALUE a;\na = rb_ary_new2(0);\nreturn a;\n}", - "RubyToAnsiC" => "void *\nempty() {\nvoid * a;\na = (void *) malloc(sizeof(void *) * 0);\nreturn a;\n}", + "cvasgn" => { + "Ruby" => "def x\n @@blah = 1\nend", + "ParseTree" => [:defn, :x, + [:scope, + [:block, [:args], [:cvasgn, :@@blah, [:lit, 1]]]]] }, - "defn_or" => { - "Ruby" => "def |()\n nil\nend", - "ParseTree" => [:defn, :|, [:scope, [:block, [:args], [:nil]]]], - "Rewriter" => s(:defn, :|, - s(:args), s(:scope, s(:block, s(:nil)))), - "TypeChecker" => t(:defn, :|, - t(:args), - t(:scope, - t(:block, - t(:nil, Type.value), - Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.void)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE\nrrc_c_or(VALUE self) {\nQnil;\n}", - "RubyToAnsiC" => "void\nor() {\nNULL;\n}", + "cvdecl" => { + "Ruby" => "class X\n @@blah = 1\n \nend", + "ParseTree" => [:class, :X, nil, + [:scope, [:cvdecl, :@@blah, [:lit, 1]]]], }, + "dasgn" => { + "Ruby" => "a.each do |x|\n b.each do |y|\n x = (x + 1)\n end\nend", + "ParseTree" => [:iter, + [:call, [:vcall, :a], :each], + [:dasgn_curr, :x], + [:iter, + [:call, [:vcall, :b], :each], + [:dasgn_curr, :y], + [:dasgn, :x, + [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]]], + }, + + "defined" => { + "Ruby" => "defined? $x", + "ParseTree" => [:defined, [:gvar, :$x]], + }, + + "defn_empty" => { + "Ruby" => "def empty\n # do nothing\nend", + "ParseTree" => [:defn, :empty, [:scope, [:block, [:args], [:nil]]]], + }, + "defn_is_something" => { - "Ruby" => "def something?()\n nil\nend", + "Ruby" => "def something?\n # do nothing\nend", "ParseTree" => [:defn, :something?, [:scope, [:block, [:args], [:nil]]]], - "Rewriter" => s(:defn, :something?, - s(:args), s(:scope, s(:block, s(:nil)))), - "TypeChecker" => t(:defn, :something?, - t(:args), - t(:scope, - t(:block, - t(:nil, Type.value), - Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.void)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE\nrrc_c_is_something(VALUE self) {\nQnil;\n}", - "RubyToAnsiC" => "void\nis_something() {\nNULL;\n}", }, - "defn_fbody" => { - "Ruby" => "def aliased()\n puts(42)\nend", - "ParseTree" => [:defn, :aliased, - [:fbody, - [:scope, - [:block, - [:args], - [:fcall, :puts, [:array, [:lit, 42]]]]]]], - "Rewriter" => s(:defn, :aliased, - s(:args), - s(:scope, - s(:block, - s(:call, nil, :puts, s(:arglist, s(:lit, 42)))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + "defn_or" => { + "Ruby" => "def |\n # do nothing\nend", + "ParseTree" => [:defn, :|, [:scope, [:block, [:args], [:nil]]]], }, + + "defn_zarray" => { # tests memory allocation for returns + "Ruby" => "def empty\n a = []\n return a\nend", + "ParseTree" => [:defn, :empty, + [:scope, + [:block, [:args], + [:lasgn, :a, [:zarray]], [:return, [:lvar, :a]]]]], + }, - "defn_optargs" => { - "Ruby" => "def x(a, *args)\n p(a, args)\nend", - "ParseTree" => [:defn, :x, + "defs" => { + "Ruby" => "def self.x(y)\n (y + 1)\nend", + "ParseTree" => [:defs, [:self], :x, [:scope, [:block, - [:args, :a, :"*args"], - [:fcall, :p, - [:array, [:lvar, :a], [:lvar, :args]]]]]], - "Rewriter" => s(:defn, :x, - s(:args, :a, :"*args"), - s(:scope, - s(:block, - s(:call, nil, :p, - s(:arglist, s(:lvar, :a), s(:lvar, :args)))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + [:args, :y], + [:call, [:lvar, :y], :+, [:array, [:lit, 1]]]]]], }, - "dmethod_added" => { - "Ruby" => "def dmethod_added\n define_method(:bmethod_added)\n x {|(x + 1)|\n }end", + "dmethod" => { + "Ruby" => [Examples, :dmethod_added], "ParseTree" => [:defn, - :dmethod_added, - [:dmethod, - :bmethod_maker, - [:scope, - [:block, - [:args], - [:iter, - [:fcall, :define_method, [:array, [:lit, :bmethod_added]]], - [:dasgn_curr, :x], - [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]]]]], - "Rewriter" => s(:defn, - :dmethod_added, - s(:args, :x), - s(:scope, - s(:block, - s(:call, s(:lvar, :x), :+, - s(:arglist, s(:lit, 1)))))), - "TypeChecker" => :skip, - "CRewriter" => :skip, - "RubyToRubyC" => :skip, - "RubyToAnsiC" => :skip, + :dmethod_added, + [:dmethod, + :bmethod_maker, + [:scope, + [:block, + [:args], + [:iter, + [:fcall, :define_method, + [:array, [:lit, :bmethod_added]]], + [:dasgn_curr, :x], + [:call, [:dvar, :x], :+, [:array, [:lit, 1]]]]]]]], + "Ruby2Ruby" => "def dmethod_added(x)\n (x + 1)\nend" }, + "dot2" => { + "Ruby" => "(a..b)", + "ParseTree" => [:dot2, [:vcall, :a], [:vcall, :b]], + }, + + "dot3" => { + "Ruby" => "(a...b)", + "ParseTree" => [:dot3, [:vcall, :a], [:vcall, :b]], + }, + + "dregx" => { + "Ruby" => "/x#\{(1 + 1)}y/", + "ParseTree" => [:dregx, "x", + [:call, [:lit, 1], :+, [:array, [:lit, 1]]], [:str, "y"]], + }, + + "dregx_once" => { + "Ruby" => "/x#\{(1 + 1)}y/o", + "ParseTree" => [:dregx_once, "x", + [:call, [:lit, 1], :+, [:array, [:lit, 1]]], [:str, "y"]], + }, + + "dstr" => { + "Ruby" => "argl = 1\n\"x#\{argl}y\"\n", + "ParseTree" => [:block, + [:lasgn, :argl, [:lit, 1]], + [:dstr, "x", [:lvar, :argl], + [:str, "y"]]], + }, + + "dsym" => { + "Ruby" => ":\"x#\{(1 + 1)}y\"", + "ParseTree" => [:dsym, "x", + [:call, [:lit, 1], :+, [:array, [:lit, 1]]], [:str, "y"]], + }, + + "dxstr" => { + "Ruby" => "t = 5\n`touch #\{t}`\n", + "ParseTree" => [:block, + [:lasgn, :t, [:lit, 5]], + [:dxstr, 'touch ', [:lvar, :t]]], + }, + + "ensure" => { + "Ruby" => "def bbegin\n begin\n (1 + 1)\n rescue SyntaxError => e1\n 2\n rescue Exception => e2\n 3\n else\n 4\n ensure\n 5\n end\nend", + "ParseTree" => [:defn, :bbegin, + [:scope, + [:block, + [:args], + [:begin, + [:ensure, + [:rescue, + [:call, [:lit, 1], :+, [:array, [:lit, 1]]], + [:resbody, + [:array, [:const, :SyntaxError]], + [:block, [:lasgn, :e1, [:gvar, :$!]], [:lit, 2]], + [:resbody, + [:array, [:const, :Exception]], + [:block, [:lasgn, :e2, [:gvar, :$!]], [:lit, 3]]]], + [:lit, 4]], + [:lit, 5]]]]]], + }, + + "false" => { + "Ruby" => "false", + "ParseTree" => [:false], + }, + + "fbody" => { + "Ruby" => [Examples, :an_alias], + "ParseTree" => [:defn, :an_alias, + [:fbody, + [:scope, + [:block, + [:args], + [:call, [:lit, 1], :+, [:array, [:lit, 1]]]]]]], + "Ruby2Ruby" => "def an_alias\n (1 + 1)\nend" + }, + + "fcall" => { + "Ruby" => "p(4)", + "ParseTree" => [:fcall, :p, [:array, [:lit, 4]]], + }, + + "flip2" => { + "Ruby" => "x = if ((i % 4) == 0)..((i % 3) == 0) then\n i\nelse\n nil\nend", + "ParseTree" => [:lasgn, + :x, + [:if, + [:flip2, + [:call, + [:call, [:vcall, :i], :%, [:array, [:lit, 4]]], + :==, + [:array, [:lit, 0]]], + [:call, + [:call, [:vcall, :i], :%, [:array, [:lit, 3]]], + :==, + [:array, [:lit, 0]]]], + [:vcall, :i], + [:nil]]], + }, + + "flip3" => { + "Ruby" => "x = if ((i % 4) == 0)...((i % 3) == 0) then\n i\nelse\n nil\nend", + "ParseTree" => [:lasgn, + :x, + [:if, + [:flip3, + [:call, + [:call, [:vcall, :i], :%, [:array, [:lit, 4]]], + :==, + [:array, [:lit, 0]]], + [:call, + [:call, [:vcall, :i], :%, [:array, [:lit, 3]]], + :==, + [:array, [:lit, 0]]]], + [:vcall, :i], + [:nil]]], + }, + + "for" => { + "Ruby" => "for o in ary\n puts(o)\nend\n", + "ParseTree" => [:for, [:vcall, :ary], [:lasgn, :o], + [:fcall, :puts, [:array, [:lvar, :o]]]], + }, + + "gasgn" => { + "Ruby" => "$x = 42", + "ParseTree" => [:gasgn, :$x, [:lit, 42]], + }, + "global" => { "Ruby" => "$stderr", "ParseTree" => [:gvar, :$stderr], - "Rewriter" => s(:gvar, :$stderr), - # TODO: test s(:gvar, :$stderr) != t(:gvar, $stderr, Type.file) - "TypeChecker" => t(:gvar, :$stderr, Type.file), - "CRewriter" => :same, - "RubyToRubyC" => "rb_gv_get(\"$stderr\")", - "RubyToAnsiC" => "stderr", }, - "interpolated" => { - "Ruby" => "\"var is \#{argl}. So there.\"", - "ParseTree" => [:dstr, - "var is ", [:lvar, :argl], [:str, ". So there."]], - "Rewriter" => s(:dstr, - "var is ", s(:lvar, :argl), s(:str, ". So there.")), - "TypeChecker" => t(:dstr, - "var is ", - t(:lvar, :argl, Type.long), - t(:str, ". So there.", Type.str), - Type.str), - "CRewriter" => :same, - "RubyToRubyC" => "rb_funcall(rb_mKernel, rb_intern(\"sprintf\"), 4, rb_str_new2(\"%s%s%s\"), rb_str_new2(\"var is \"), argl, rb_str_new2(\". So there.\"))", - "RubyToAnsiC" => :unsupported, + "gvar" => { + "Ruby" => "$x", + "ParseTree" => [:gvar, :$x], }, - "iter" => { + "hash" => { + "Ruby" => "{ 1 => 2, 3 => 4 }", + "ParseTree" => [:hash, [:lit, 1], [:lit, 2], [:lit, 3], [:lit, 4]], + }, + + "iasgn" => { + "Ruby" => "@a = 4", + "ParseTree" => [:iasgn, :@a, [:lit, 4]], + }, + + "iteration1" => { "Ruby" => "loop do end", "ParseTree" => [:iter, [:fcall, :loop], nil], - "Rewriter" => s(:iter, - s(:call, nil, :loop, nil), - s(:dasgn_curr, :temp_1), - nil), - "TypeChecker" => t(:iter, - t(:call, nil, :loop, nil, Type.unknown), - t(:dasgn_curr, :temp_1, Type.unknown), - nil, - Type.unknown), - "CRewriter" => [:defx, - t(:iter, - t(:call, nil, :loop, nil, Type.unknown), - t(:args, - t(:array, t(:dasgn_curr, :temp_1, Type.unknown), Type.void), - t(:array, Type.void), Type.void), - t(:call, nil, - :temp_2, - s(:arglist, s(:dasgn_curr, :temp_1, Type.unknown), - t(:nil)))), - [t(:defx, - :temp_2, - t(:args, :temp_2, :temp_3), - t(:scope, t(:block, nil)), Type.void)]], - "RubyToRubyC" => "", - "RubyToAnsiC" => "", }, "iteration2" => { + "Ruby" => "array = [1, 2, 3]\narray.each do |x|\n puts(x.to_s)\nend\n", + "ParseTree" => [:block, + [:lasgn, :array, + [:array, [:lit, 1], [:lit, 2], [:lit, 3]]], + [:iter, + [:call, [:lvar, :array], :each], + [:dasgn_curr, :x], + [:fcall, :puts, [:array, [:call, [:dvar, :x], :to_s]]]]], + }, + + "iteration3" => { + "Ruby" => "1.upto(3) do |n|\n puts(n.to_s)\nend", "ParseTree" => [:iter, - [:call, [:lvar, :arrays], :each], - [:dasgn_curr, :x], - [:fcall, :puts, [:arrays, [:dvar, :x]]]], - "Rewriter" => s(:iter, - s(:call, s(:lvar, :arrays), :each, nil), - s(:dasgn_curr, :x), - s(:call, nil, :puts, s(:arglist, s(:dvar, :x)))), - "TypeChecker" => t(:iter, - t(:call, - t(:lvar, :arrays, Type.str_list), - :each, - nil, Type.unknown), - t(:dasgn_curr, :x, Type.str), - t(:call, nil, :puts, - t(:arglist, t(:dvar, :x, Type.str)), - Type.void), - Type.void), - "CRewriter" => [:defx, - t(:iter, - t(:call, - t(:lvar, :arrays, Type.str_list), - :each, - nil, Type.unknown), - t(:args, - t(:array, t(:dasgn_curr, :x, Type.str), Type.void), - t(:array, t(:lvar, :arrays, Type.value), Type.void), Type.void), - t(:call, nil, :temp_1, t(:arglist, t(:dasgn_curr, :x, Type.str), t(:nil)))), - [t(:defx, - :temp_1, - t(:args, :temp_2, :temp_3), - t(:scope, - t(:block, - t(:call, - nil, - :puts, - t(:arglist, t(:dvar, :x, Type.str)), Type.void))), Type.void)]], - "RubyToRubyC" => 'unsigned long index_temp_1; -VALUE temp_2 = rb_funcall(arrays, rb_intern("to_a"), 0); -unsigned long temp_1_max = FIX2LONG(rb_funcall(temp_2, rb_intern("size"), 0)); -for (index_temp_1 = 0; index_temp_1 < temp_1_max; ++index_temp_1) { -VALUE x; -x = rb_funcall(temp_2, rb_intern("at"), 1, LONG2FIX(index_temp_1)); -rb_funcall(self, rb_intern("puts"), 1, x); -}", - "RubyToAnsiC" => "unsigned long index_x; -for (index_x = 0; arrays[index_x] != NULL; ++index_x) { -str x = arrays[index_x]; -puts(x); -}', + [:call, [:lit, 1], :upto, [:array, [:lit, 3]]], + [:dasgn_curr, :n], + [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]], }, - "iteration4" => { - "Ruby" => "1.upto(3) {|n|\n puts(n.to_s)\n}", + "Ruby" => "3.downto(1) do |n|\n puts(n.to_s)\nend", "ParseTree" => [:iter, - [:call, [:lit, 1], :upto, [:array, [:lit, 3]]], - [:dasgn_curr, :n], - [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]], - "Rewriter" => s(:dummy, - s(:lasgn, :n, s(:lit, 1)), - s(:while, - s(:call, s(:lvar, :n), :<=, s(:arglist, s(:lit, 3))), - s(:block, - s(:call, - nil, - :puts, - s(:arglist, s(:call, s(:lvar, :n), :to_s, nil))), - s(:lasgn, :n, - s(:call, s(:lvar, :n), - :+, - s(:arglist, s(:lit, 1))))), true)), - "TypeChecker" => t(:dummy, t(:lasgn, :n, t(:lit, 1, Type.long), Type.long), - t(:while, - t(:call, - t(:lvar, :n, Type.long), - :<=, - t(:arglist, t(:lit, 3, Type.long)), Type.bool), - t(:block, - t(:call, nil, :puts, - t(:arglist, - t(:call, - t(:lvar, :n, Type.long), - :to_s, - nil, Type.str)), Type.void), - t(:lasgn, :n, - t(:call, - t(:lvar, :n, Type.long), - :+, - t(:arglist, - t(:lit, - 1, Type.long)), - Type.long), Type.long), Type.unknown), true)), - "CRewriter" => :same, - "RubyToRubyC" => '', - "RubyToAnsiC" => 'n = 1; -while (n <= 3) { -puts(to_s(n)); -n = n + 1; -}', + [:call, [:lit, 3], :downto, [:array, [:lit, 1]]], + [:dasgn_curr, :n], + [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]], }, "iteration5" => { - "Ruby" => "3.downto(1) {|n|\n puts(n.to_s)\n}", - "ParseTree" => [:iter, - [:call, [:lit, 3], :downto, [:array, [:lit, 1]]], - [:dasgn_curr, :n], - [:fcall, :puts, [:array, [:call, [:dvar, :n], :to_s]]]], - "Rewriter" => s(:dummy, s(:lasgn, :n, s(:lit, 3)), s(:while, - s(:call, s(:lvar, :n), :>=, s(:arglist, s(:lit, 1))), - s(:block, - s(:call, nil, :puts, - s(:arglist, s(:call, s(:lvar, :n), :to_s, nil))), - s(:lasgn, :n, s(:call, s(:lvar, :n), - :-, s(:arglist, s(:lit, 1))))), true)), - "TypeChecker" => t(:dummy, - t(:lasgn, :n, t(:lit, 3, Type.long), Type.long), - t(:while, - t(:call, - t(:lvar, :n, Type.long), - :>=, - t(:arglist, t(:lit, 1, Type.long)), Type.bool), - t(:block, - t(:call, nil, :puts, - t(:arglist, - t(:call, - t(:lvar, :n, Type.long), - :to_s, - nil, Type.str)), Type.void), - t(:lasgn, :n, - t(:call, - t(:lvar, :n, Type.long), - :-, - t(:arglist, t(:lit, 1, Type.long)), - Type.long), - Type.long), - Type.unknown), true)), - "CRewriter" => :same, - "RubyToRubyC" => '', - "RubyToAnsiC" => 'n = 3; -while (n >= 1) { -puts(to_s(n)); -n = n - 1; -}', + "Ruby" => "argl = 10\nwhile (argl >= 1) do\n puts(\"hello\")\n argl = (argl - 1)\nend\n", + "ParseTree" => [:block, + [:lasgn, :argl, [:lit, 10]], + [:while, + [:call, [:lvar, :argl], :>=, [:array, [:lit, 1]]], + [:block, + [:fcall, :puts, [:array, [:str, "hello"]]], + [:lasgn, + :argl, + [:call, [:lvar, :argl], + :-, [:array, [:lit, 1]]]]], true]], }, "iteration6" => { - "Ruby" => "while ((argl >= (1))) do\nputs((\"hello\"))\nargl = (argl - (1))\n\nend", - "ParseTree" => [:while, [:call, [:lvar, :argl], - :>=, [:arglist, [:lit, 1]]], [:block, - [:call, nil, :puts, [:arglist, [:str, "hello"]]], - [:lasgn, - :argl, - [:call, [:lvar, :argl], - :-, [:arglist, [:lit, 1]]]]], true], - "Rewriter" => s(:while, - s(:call, s(:lvar, :argl), - :>=, s(:arglist, s(:lit, 1))), - s(:block, - s(:call, nil, :puts, s(:arglist, s(:str, "hello"))), - s(:lasgn, - :argl, - s(:call, s(:lvar, :argl), - :-, s(:arglist, s(:lit, 1))))), true), - "TypeChecker" => t(:while, - t(:call, t(:lvar, :argl, Type.long), - :>=, - t(:arglist, t(:lit, 1, Type.long)), Type.bool), - t(:block, - t(:call, nil, :puts, - t(:arglist, t(:str, "hello", Type.str)), - Type.void), - t(:lasgn, - :argl, - t(:call, t(:lvar, :argl, Type.long), - :-, - t(:arglist, t(:lit, 1, Type.long)), Type.long), - Type.long), - Type.unknown), true), - "CRewriter" => :same, - "RubyToRubyC" => '', - "RubyToAnsiC" => 'while (argl >= 1) { -puts("hello"); -argl = argl - 1; -}', + "Ruby" => "array1 = [1, 2, 3]\narray2 = [4, 5, 6, 7]\narray1.each do |x|\n array2.each do |y|\n puts(x.to_s)\n puts(y.to_s)\n end\nend\n", + "ParseTree" => [:block, + [:lasgn, :array1, + [:array, [:lit, 1], [:lit, 2], [:lit, 3]]], + [:lasgn, :array2, + [:array, [:lit, 4], [:lit, 5], [:lit, 6], [:lit, 7]]], + [:iter, + [:call, + [:lvar, :array1], :each], + [:dasgn_curr, :x], + [:iter, + [:call, + [:lvar, :array2], :each], + [:dasgn_curr, :y], + [:block, + [:fcall, :puts, + [:array, [:call, [:dvar, :x], :to_s]]], + [:fcall, :puts, + [:array, [:call, [:dvar, :y], :to_s]]]]]]], }, - # TODO: this might still be too much - "lasgn_call" => { - "Ruby" => "c = 2 + 3", - "ParseTree" => [:lasgn, :c, [:call, [:lit, 2], :+, [:arglist, [:lit, 3]]]], - "Rewriter" => s(:lasgn, :c, s(:call, s(:lit, 2), :+, s(:arglist, s(:lit, 3)))), - "TypeChecker" => t(:lasgn, :c, - t(:call, - t(:lit, 2, Type.long), - :+, - t(:arglist, - t(:lit, 3, Type.long)), - Type.long), - Type.long), - "CRewriter" => :same, - "RubyToRubyC" => 'c = rb_funcall(LONG2NUM(2), rb_intern("+"), 1, LONG2NUM(3))', # FIX: probably not "c =" - "RubyToAnsiC" => "c = 2 + 3", + "ivar" => { + "Ruby" => [Examples, :reader], + "ParseTree" => [:defn, :reader, [:ivar, :@reader]], + "Ruby2Ruby" => "attr_reader :reader" }, "lasgn_array" => { "Ruby" => "var = [\"foo\", \"bar\"]", "ParseTree" => [:lasgn, :var, [:array, - [:str, "foo"], - [:str, "bar"]]], - "Rewriter" => s(:lasgn, :var, s(:array, - s(:str, "foo"), - s(:str, "bar"))), - "TypeChecker" => t(:lasgn, - :var, - t(:array, - t(:str, "foo", Type.str), - t(:str, "bar", Type.str)), - Type.str_list), - "CRewriter" => :same, - "RubyToRubyC" => 'var = rb_ary_new2(2); -rb_ary_store(var, 0, rb_str_new2("foo")); -rb_ary_store(var, 1, rb_str_new2("bar"))', - "RubyToAnsiC" => 'var = (str) malloc(sizeof(str) * 2); -var[0] = "foo"; -var[1] = "bar"' -}, + [:str, "foo"], + [:str, "bar"]]], + }, + "lasgn_call" => { + "Ruby" => "c = (2 + 3)", + "ParseTree" => [:lasgn, :c, [:call, [:lit, 2], :+, [:array, [:lit, 3]]]], + }, + "lit_bool_false" => { "Ruby" => "false", "ParseTree" => [:false], - "Rewriter" => s(:false), - "TypeChecker" => t(:false, Type.bool), - "CRewriter" => :same, - "RubyToRubyC" => "Qfalse", - "RubyToAnsiC" => "0", }, "lit_bool_true" => { "Ruby" => "true", "ParseTree" => [:true], - "Rewriter" => s(:true), - "TypeChecker" => t(:true, Type.bool), - "CRewriter" => :same, - "RubyToRubyC" => "Qtrue", - "RubyToAnsiC" => "1", }, "lit_float" => { "Ruby" => "1.1", "ParseTree" => [:lit, 1.1], - "Rewriter" => s(:lit, 1.1), - "TypeChecker" => t(:lit, 1.1, Type.float), - "CRewriter" => :same, - "RubyToRubyC" => "rb_float_new(1.1)", - "RubyToAnsiC" => "1.1", }, "lit_long" => { "Ruby" => "1", "ParseTree" => [:lit, 1], - "Rewriter" => s(:lit, 1), - "TypeChecker" => t(:lit, 1, Type.long), - "CRewriter" => :same, - "RubyToRubyC" => "LONG2NUM(1)", - "RubyToAnsiC" => "1", }, - "lit_sym" => { - "Ruby" => ":x", - "ParseTree" => [:lit, :x], - "Rewriter" => s(:lit, :x), - "TypeChecker" => t(:lit, :x, Type.symbol), - "CRewriter" => :same, - "RubyToRubyC" => 'ID2SYM(rb_intern("x"))', - "RubyToAnsiC" => '"x"', # HACK WRONG! (or... is it?) + "lit_range2" => { + "Ruby" => "(1..10)", + "ParseTree" => [:lit, 1..10], }, + "lit_range3" => { + "Ruby" => "(1...10)", + "ParseTree" => [:lit, 1...10], + }, + + "lit_regexp" => { + "Ruby" => "/x/", + "ParseTree" => [:lit, /x/], + }, + "lit_str" => { "Ruby" => "\"x\"", "ParseTree" => [:str, "x"], - "Rewriter" => s(:str, "x"), - "TypeChecker" => t(:str, "x", Type.str), - "CRewriter" => :same, - "RubyToRubyC" => 'rb_str_new2("x")', - "RubyToAnsiC" => '"x"', }, - "multi_args" => { - "Ruby" => "def multi_args(arg1, arg2)\n arg3 = ((arg1 * arg2) * 7)\n puts(arg3.to_s)\n return \"foo\"\nend", - "ParseTree" => [:defn, :multi_args, - [:scope, - [:block, - [:args, :arg1, :arg2], - [:lasgn, - :arg3, - [:call, - [:call, [:lvar, :arg1], :*, [:array, [:lvar, :arg2]]], - :*, - [:array, [:lit, 7]]]], - [:fcall, :puts, [:array, [:call, [:lvar, :arg3], :to_s]]], - [:return, [:str, "foo"]]]]], - "Rewriter" => s(:defn, :multi_args, - s(:args, :arg1, :arg2), - s(:scope, - s(:block, - s(:lasgn, :arg3, - s(:call, - s(:call, - s(:lvar, :arg1), - :*, - s(:arglist, s(:lvar, :arg2))), - :*, - s(:arglist, s(:lit, 7)))), - s(:call, - nil, - :puts, - s(:arglist, - s(:call, - s(:lvar, :arg3), - :to_s, - nil))), - s(:return, s(:str, "foo"))))), - "TypeChecker" => t(:defn, :multi_args, - t(:args, - t(:arg1, Type.long), - t(:arg2, Type.long)), - t(:scope, - t(:block, - t(:lasgn, - :arg3, - t(:call, - t(:call, - t(:lvar, :arg1, Type.long), - :*, - t(:arglist, - t(:lvar, - :arg2, - Type.long)), - Type.long), - :*, - t(:arglist, - t(:lit, 7, Type.long)), - Type.long), - Type.long), - t(:call, - nil, - :puts, - t(:arglist, - t(:call, - t(:lvar, :arg3, Type.long), - :to_s, - nil, - Type.str)), - Type.void), - t(:return, t(:str, "foo", Type.str), - Type.void), - Type.unknown), - Type.void), - Type.function(Type.unknown, - [Type.long, Type.long], Type.str)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE -rrc_c_multi_args(VALUE self, VALUE arg1, VALUE arg2) { -VALUE arg3; -arg3 = rb_funcall(rb_funcall(arg1, rb_intern(\"*\"), 1, arg2), rb_intern(\"*\"), 1, LONG2NUM(7)); -rb_funcall(self, rb_intern(\"puts\"), 1, rb_funcall(arg3, rb_intern(\"to_s\"), 0)); -return rb_str_new2(\"foo\"); -}", - "RubyToAnsiC" => "str -multi_args(long arg1, long arg2) { -long arg3; -arg3 = arg1 * arg2 * 7; -puts(to_s(arg3)); -return \"foo\"; -}", + "lit_sym" => { + "Ruby" => ":x", + "ParseTree" => [:lit, :x], }, - + + "masgn" => { + "Ruby" => "a, b = c, d", + "ParseTree" => [:masgn, + [:array, [:lasgn, :a], [:lasgn, :b]], + [:array, [:vcall, :c], [:vcall, :d]]], + }, + + "match" => { + "Ruby" => "if /x/ then\n 1\nend", + "ParseTree" => [:if, [:match, [:lit, /x/]], [:lit, 1], nil], + }, + + "match2" => { + "Ruby" => "/x/ =~ \"blah\"", + "ParseTree" => [:match2, [:lit, /x/], [:str, "blah"]], + }, + + "match3" => { + "Ruby" => "\"blah\" =~ /x/", + "ParseTree" => [:match3, [:lit, /x/], [:str, "blah"]], + }, + + "module" => { + "Ruby" => "module X\n def y\n # do nothing\n end\n \nend", + "ParseTree" => [:module, :X, + [:scope, + [:defn, :y, [:scope, [:block, [:args], [:nil]]]]]], + }, + + "next" => { + "Ruby" => "loop do\n if false then\n next\n end\nend", + "ParseTree" => [:iter, + [:fcall, :loop], + nil, + [:if, [:false], [:next], nil]], + }, + + "not" => { + "Ruby" => "(not true)", + "ParseTree" => [:not, [:true]], + }, + + "nth_ref" => { + "Ruby" => "$1", + "ParseTree" => [:nth_ref, 1], + }, + + "op_asgn1" => { + "Ruby" => "b = []\nb[1] ||= 10\nb[2] &&= 11\nb[3] += 12\n", + "ParseTree" => [:block, + [:lasgn, :b, [:zarray]], + [:op_asgn1, [:lvar, :b], + [:array, [:lit, 1]], "||".intern, [:lit, 10]], # s->e + [:op_asgn1, [:lvar, :b], + [:array, [:lit, 2]], "&&".intern, [:lit, 11]], # s->e + [:op_asgn1, [:lvar, :b], + [:array, [:lit, 3]], :+, [:lit, 12]]], + }, + + "op_asgn2" => { + "Ruby" => "s = Struct.new(:var)\nc = s.new(nil)\nc.var ||= 20\nc.var &&= 21\nc.var += 22\nc.d.e.f ||= 42\n", + "ParseTree" => [:block, + [:lasgn, :s, + [:call, [:const, :Struct], + :new, [:array, [:lit, :var]]]], + [:lasgn, :c, + [:call, [:lvar, :s], :new, [:array, [:nil]]]], + + [:op_asgn2, [:lvar, :c], :var=, "||".intern, # s->e + [:lit, 20]], + [:op_asgn2, [:lvar, :c], :var=, "&&".intern, # s->e + [:lit, 21]], + [:op_asgn2, [:lvar, :c], :var=, :+, [:lit, 22]], + + [:op_asgn2, + [:call, + [:call, [:lvar, :c], :d], :e], :f=, "||".intern, + [:lit, 42]]], + }, + + "op_asgn_and" => { + "Ruby" => "a = 0\na &&= 2\n", + "ParseTree" => [:block, + [:lasgn, :a, [:lit, 0]], + [:op_asgn_and, [:lvar, :a], [:lasgn, :a, [:lit, 2]]]], + }, + + "op_asgn_or" => { + "Ruby" => "a = 0\na ||= 1\n", + "ParseTree" => [:block, + [:lasgn, :a, [:lit, 0]], + [:op_asgn_or, [:lvar, :a], [:lasgn, :a, [:lit, 1]]]], + }, + + "or" => { + "Ruby" => "(a or b)", + "ParseTree" => [:or, [:vcall, :a], [:vcall, :b]], + }, + + "postexe" => { + "Ruby" => "END {\n 1\n}", + "ParseTree" => [:iter, [:postexe], nil, [:lit, 1]], + }, + + "redo" => { + "Ruby" => "loop do\n if false then\n redo\n end\nend", + "ParseTree" => [:iter, + [:fcall, :loop], nil, [:if, [:false], [:redo], nil]], + }, + +# "rescue" => { # TODO: expression style rescues +# "Ruby" => "blah rescue nil", +# "ParseTree" => [:rescue, [:vcall, :blah], [:resbody, nil, [:nil]]], +# }, + + "rescue_block" => { + "Ruby" => "begin\n blah\nrescue\n # do nothing\nend\n", + "ParseTree" => [:begin, [:rescue, [:vcall, :blah], [:resbody, nil]]] + }, + + "rescue_exceptions" => { + "Ruby" => "begin\n blah\nrescue RuntimeError => r\n # do nothing\nend\n", + "ParseTree" => [:begin, + [:rescue, + [:vcall, :blah], + [:resbody, + [:array, [:const, :RuntimeError]], + [:lasgn, :r, [:gvar, :$!]]]]], + }, + + "retry" => { + "Ruby" => "retry", + "ParseTree" => [:retry], + }, + + "sclass" => { + "Ruby" => "class << self\n 42\nend", + "ParseTree" => [:sclass, [:self], [:scope, [:lit, 42]]], + }, + + "splat" => { + "Ruby" => "a(*b)", + "ParseTree" => [:fcall, :a, [:splat, [:vcall, :b]]], + }, + + "super" => { + "Ruby" => "def x\n super(4)\nend", + "ParseTree" => [:defn, :x, + [:scope, + [:block, + [:args], + [:super, [:array, [:lit, 4]]]]]], + }, + + "super_multi" => { + "Ruby" => "def x\n super(4, 2, 1)\nend", + "ParseTree" => [:defn, :x, + [:scope, + [:block, + [:args], + [:super, [:array, [:lit, 4], [:lit, 2], [:lit, 1]]]]]], + }, + + "svalue" => { + "Ruby" => "a = *b", + "ParseTree" => [:lasgn, :a, [:svalue, [:splat, [:vcall, :b]]]], + }, + + "to_ary" => { + "Ruby" => "a, b = c", + "ParseTree" => [:masgn, + [:array, [:lasgn, :a], [:lasgn, :b]], + [:to_ary, [:vcall, :c]]], + }, + + "true" => { + "Ruby" => "true", + "ParseTree" => [:true], + }, + + "undef" => { + "Ruby" => "undef :x", + "ParseTree" => [:undef, [:lit, :x]], + }, + + "undef_multi" => { + "Ruby" => "undef :x, :y, :z", + "ParseTree" => [:block, + [:undef, [:lit, :x]], + [:undef, [:lit, :y]], + [:undef, [:lit, :z]]], + "Ruby2Ruby" => "undef :x\nundef :y\nundef :z\n", + }, + + "until" => { + "Ruby" => "until false do\n (1 + 1)\nend", + "ParseTree" => [:until, [:false], + [:call, [:lit, 1], :+, [:array, [:lit, 1]]], true], + }, + + "valias" => { + "Ruby" => "alias $y $x", + "ParseTree" => [:valias, :$y, :$x], + }, + "vcall" => { "Ruby" => "method", "ParseTree" => [:vcall, :method], - "Rewriter" => s(:call, nil, :method, nil), - "TypeChecker" => t(:call, nil, :method, nil, Type.unknown), - "CRewriter" => :same, - "RubyToRubyC" => "rb_funcall(self, rb_intern(\"method\"), 0)", - "RubyToAnsiC" => "method()", }, "whiles" => { - "Ruby" => "def whiles()\n while (false) do\n puts(\"false\")\n end\n begin\n puts(\"true\")\n end while (false)\nend", + "Ruby" => "def whiles\n while false do\n puts(\"false\")\n end\n begin\n puts(\"true\")\n end while false\nend", "ParseTree" => [:defn, - :whiles, - [:scope, - [:block, - [:args], - [:while, [:false], - [:fcall, :puts, [:array, [:str, "false"]]], true], - [:while, [:false], - [:fcall, :puts, [:array, [:str, "true"]]], false]]]], - "Rewriter" => s(:defn, - :whiles, - s(:args), - s(:scope, - s(:block, - s(:while, - s(:false), - s(:call, nil, :puts, s(:arglist, s(:str, "false"))), - true), - s(:while, - s(:false), - s(:call, nil, :puts, s(:arglist, s(:str, "true"))), - false)))), - "TypeChecker" => t(:defn, - :whiles, - t(:args), - t(:scope, - t(:block, - t(:while, - t(:false, Type.bool), - t(:call, - nil, - :puts, - t(:arglist, t(:str, "false", Type.str)), Type.void), - true), - t(:while, - t(:false, Type.bool), - t(:call, - nil, - :puts, - t(:arglist, t(:str, "true", Type.str)), Type.void), - false), - Type.unknown), - Type.void), - Type.function(Type.unknown, [], Type.void)), - "CRewriter" => :same, - "RubyToRubyC" => "static VALUE -rrc_c_whiles(VALUE self) { -while (Qfalse) { -rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"false\")); -}; -{ -rb_funcall(self, rb_intern(\"puts\"), 1, rb_str_new2(\"true\")); -} while (Qfalse); -}", - "RubyToAnsiC" => "void -whiles() { -while (0) { -puts(\"false\"); -}; -{ -puts(\"true\"); -} while (0); -}", + :whiles, + [:scope, + [:block, + [:args], + [:while, [:false], + [:fcall, :puts, [:array, [:str, "false"]]], true], + [:while, [:false], + [:fcall, :puts, [:array, [:str, "true"]]], false]]]], }, + "xstr" => { + "Ruby" => "`touch 5`", + "ParseTree" => [:xstr, 'touch 5'], + }, + + "yield" => { + "Ruby" => "yield", + "ParseTree" => [:yield], + }, + + "yield_arg" => { + "Ruby" => "yield(42)", + "ParseTree" => [:yield, [:lit, 42]], + }, + + "yield_args" => { + "Ruby" => "yield(42, 24)", + "ParseTree" => [:yield, [:array, [:lit, 42], [:lit, 24]]], + }, + "zarray" => { "Ruby" => "a = []", "ParseTree" => [:lasgn, :a, [:zarray]], - "Rewriter" => s(:lasgn, :a, s(:array)), - "TypeChecker" => t(:lasgn, :a, t(:array), Type.unknown_list), - "CRewriter" => :same, - # TODO: need to verify that our variable decl will be correct - "RubyToRubyC" => "a = rb_ary_new2(0)", - "RubyToAnsiC" => "a = (void *) malloc(sizeof(void *) * 0)", }, + + "zsuper" => { + "Ruby" => "def x\n super\nend", + "ParseTree" => [:defn, :x, [:scope, [:block, [:args], [:zsuper]]]], + }, } +# def test_audit_nodes +# # TODO: audit @@testcases.keys against node list - do two way audit, rename everything +# nodes = ParseTree::NODE_NAMES.map { |s| s.to_s }.sort +# tested = @@testcases.keys.map { |s| s.to_s }.sort +# if processor.respond_to? :unsupported then +# nodes -= processor.unsupported +# else +# SexpProcessor.new.unsupported +# # HACK +# nodes -= [:alloca, :argspush, :cfunc, :cref, :evstr, :ifunc, :last, :memo, :newline, :opt_n, :method].map { |s| s.to_s } +# end + +# untested = nodes-tested + +# puts +# p :untested_nodes => untested, :extra_nodes => tested-nodes + +# untested.each do |node| +# puts %( +# "#{node}" => { +# "Ruby" => "XXX", +# "ParseTree" => [], +# }, +# ) +# end + +# flunk +# end + def self.previous(key) idx = @@testcase_order.index(key)-1 case key when "RubyToRubyC" then idx -= 1 @@ -1357,10 +958,11 @@ processor.process(input) end else extra_expected = [] extra_input = [] + _, expected, extra_expected = *expected if Array === expected and expected.first == :defx _, input, extra_input = *input if Array === input and input.first == :defx assert_equal expected, processor.process(input) extra_input.each do |input| processor.process(input) end @@ -1369,10 +971,7 @@ end end end end - def test_stoopid - # do nothing - shuts up empty test class requirement - end - + undef_method :default_test end