Skip to content

Commit

Permalink
Make :iter part of relevant :call sexp (not other way around)
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Sep 25, 2013
1 parent d387311 commit bfad53f
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 85 deletions.
32 changes: 11 additions & 21 deletions lib/opal/grammar.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 11 additions & 21 deletions lib/opal/grammar.y
Expand Up @@ -810,19 +810,14 @@ primary:
}
| operation brace_block
{
result = val[1]
result[1] = new_call(nil, val[0].intern, s(:arglist))
result = new_call nil, val[0].intern, s(:arglist)
result << val[1]
}
| method_call
| method_call brace_block
{
if val[0][0] == :super
val[0] << val[1]
result = val[0]
else
result = val[1]
result[1] = val[0]
end
val[0] << val[1]
result = val[0]
}
| LAMBDA lambda
{
Expand Down Expand Up @@ -984,8 +979,8 @@ do:
lambda:
f_larglist lambda_body
{
call = new_call nil, :lambda, s(:arglist)
result = new_iter call, val[0], val[1]
result = new_call nil, :lambda, s(:arglist)
result << new_iter(val[0], val[1])
}

f_larglist:
Expand Down Expand Up @@ -1126,21 +1121,16 @@ do_block:
}
opt_block_var compstmt END
{
result = new_iter nil, val[2], val[3]
result = new_iter val[2], val[3]
result.line = val[1]
pop_scope
}

block_call:
command do_block
{
if val[0][0] == :super
val[0] << val[1]
result = val[0]
else
result = val[1]
result[1] = val[0]
end
val[0] << val[1]
result = val[0]
}
| block_call '.' operation2 opt_paren_args
| block_call '::' operation2 opt_paren_args
Expand Down Expand Up @@ -1183,7 +1173,7 @@ brace_block:
}
opt_block_var compstmt '}'
{
result = new_iter nil, val[2], val[3]
result = new_iter val[2], val[3]
result.line = val[1]
pop_scope
}
Expand All @@ -1194,7 +1184,7 @@ brace_block:
}
opt_block_var compstmt END
{
result = new_iter nil, val[2], val[3]
result = new_iter val[2], val[3]
result.line = val[1]
pop_scope
}
Expand Down
4 changes: 2 additions & 2 deletions lib/opal/grammar_helpers.rb
Expand Up @@ -76,8 +76,8 @@ def new_module(path, body)
s
end

def new_iter(call, args, body)
s = s(:iter, call, args)
def new_iter(args, body)
s = s(:iter, args)
s << body if body
s.end_line = @line
s
Expand Down
11 changes: 5 additions & 6 deletions lib/opal/parser.rb
Expand Up @@ -711,9 +711,9 @@ def process_block_pass(exp, level)
end

# A block/iter with embeded call. Compiles into function
# s(:iter, call, block_args [, body) => (function() { ... })
# s(:iter, block_args [, body) => (function() { ... })
def process_iter(sexp, level)
call, args, body = sexp
args, body = sexp

body ||= s(:nil)
body = returns body
Expand Down Expand Up @@ -805,8 +805,7 @@ def process_iter(sexp, level)
itercode.unshift f("(#{identity} = ", sexp)
itercode << f(", #{identity}._s = #{current_self}, #{identity})", sexp)

call << itercode
process call, level
itercode
end

# Maps block args into array of jsid. Adds $ suffix to invalid js
Expand All @@ -826,7 +825,7 @@ def js_block_args(sexp)
raise "Bad js_block_arg: #{arg[0]}"
end
end

result
end

Expand Down Expand Up @@ -867,7 +866,7 @@ def process_call(sexp, level)
if Array === arglist.last and arglist.last.first == :block_pass
block = process(arglist.pop)
elsif iter
block = iter
block = process(iter)
end

recv ||= s(:self)
Expand Down
30 changes: 15 additions & 15 deletions spec/parser/iter_spec.rb
Expand Up @@ -3,57 +3,57 @@
describe "Iters" do
describe "Iter on a command" do
it "the outer command call gets the iter" do
opal_parse("a b do; end").should == [:iter, [:call, nil, :a, [:arglist, [:call, nil, :b, [:arglist]]]], nil]
opal_parse("a 1, b do; end").should == [:iter, [:call, nil, :a, [:arglist, [:int, 1], [:call, nil, :b, [:arglist]]]], nil]
opal_parse("a b do; end").should == [:call, nil, :a, [:arglist, [:call, nil, :b, [:arglist]]], [:iter, nil]]
opal_parse("a 1, b do; end").should == [:call, nil, :a, [:arglist, [:int, 1], [:call, nil, :b, [:arglist]]], [:iter, nil]]
end
end

describe "with no args" do
it "has 'nil' as the args part of sexp" do
opal_parse("proc do; end")[2].should == nil
opal_parse("proc do; end")[4][1].should == nil
end
end

describe "with empty || args" do
it "should have args set to 0" do
opal_parse("proc do ||; end")[2].should == 0
opal_parse("proc do ||; end")[4][1].should == 0
end
end

describe "with normal args" do
it "adds a single s(:lasgn) for 1 norm arg" do
opal_parse("proc do |a|; end")[2].should == [:lasgn, :a]
opal_parse("proc do |a|; end")[4][1].should == [:lasgn, :a]
end

it "lists multiple norm args inside a s(:masgn)" do
opal_parse("proc do |a, b|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
opal_parse("proc do |a, b, c|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
opal_parse("proc do |a, b|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
opal_parse("proc do |a, b, c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
end
end

describe "with splat arg" do
it "adds a s(:masgn) for the s(:splat) even if its the only arg" do
opal_parse("proc do |*a|; end")[2].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
opal_parse("proc do |a, *b|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
opal_parse("proc do |*a|; end")[4][1].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
opal_parse("proc do |a, *b|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
end
end

describe "with opt args" do
it "adds a s(:block) arg to end of s(:masgn) for each lasgn" do
opal_parse("proc do |a = 1|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
opal_parse("proc do |a = 1, b = 2|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
opal_parse("proc do |a = 1|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
opal_parse("proc do |a = 1, b = 2|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
end

it "should add lasgn block after all other args" do
opal_parse("proc do |a, b = 1|; end")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :b, [:int, 1]]]]]
opal_parse("proc do |b = 1, *c|; end")[2].should == [:masgn, [:array, [:lasgn, :b], [:splat, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
opal_parse("proc do |b = 1, &c|; end")[2].should == [:masgn, [:array, [:lasgn, :b], [:block_pass, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
opal_parse("proc do |a, b = 1|; end")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :b, [:int, 1]]]]]
opal_parse("proc do |b = 1, *c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :b], [:splat, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
opal_parse("proc do |b = 1, &c|; end")[4][1].should == [:masgn, [:array, [:lasgn, :b], [:block_pass, [:lasgn, :c]], [:block, [:lasgn, :b, [:int, 1]]]]]
end
end

describe "with block arg" do
it "should add block arg with s(:block_pass) wrapping s(:lasgn) prefix" do
opal_parse("proc do |&a|; end")[2].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
opal_parse("proc do |&a|; end")[4][1].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
end
end
end
34 changes: 17 additions & 17 deletions spec/parser/lambda_spec.rb
Expand Up @@ -2,63 +2,63 @@

describe "Lambda literals" do
it "should parse with either do/end construct or curly braces" do
opal_parse("-> {}").first.should == :iter
opal_parse("-> do; end").first.should == :iter
opal_parse("-> {}").first.should == :call
opal_parse("-> do; end").first.should == :call
end

it "should parse as a call to 'lambda' with the lambda body as a block" do
opal_parse("-> {}").should == [:iter, [:call, nil, :lambda, [:arglist]], nil]
opal_parse("-> {}").should == [:call, nil, :lambda, [:arglist], [:iter, nil]]
end

describe "with no args" do
it "should accept no args" do
opal_parse("-> {}")[2].should == nil
opal_parse("-> {}")[4][1].should == nil
end
end

describe "with normal args" do
it "adds a single s(:lasgn) for 1 norm arg" do
opal_parse("->(a) {}")[2].should == [:lasgn, :a]
opal_parse("->(a) {}")[4][1].should == [:lasgn, :a]
end

it "lists multiple norm args inside a s(:masgn)" do
opal_parse("-> (a, b) {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
opal_parse("-> (a, b, c) {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
opal_parse("-> (a, b) {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
opal_parse("-> (a, b, c) {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:lasgn, :c]]]
end
end

describe "with optional braces" do
it "parses normal args" do
opal_parse("-> a {}")[2].should == [:lasgn, :a]
opal_parse("-> a, b {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
opal_parse("-> a {}")[4][1].should == [:lasgn, :a]
opal_parse("-> a, b {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b]]]
end

it "parses splat args" do
opal_parse("-> *a {}")[2].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
opal_parse("-> a, *b {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
opal_parse("-> *a {}")[4][1].should == [:masgn, [:array, [:splat, [:lasgn, :a]]]]
opal_parse("-> a, *b {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:splat, [:lasgn, :b]]]]
end

it "parses opt args" do
opal_parse("-> a = 1 {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
opal_parse("-> a = 1, b = 2 {}")[2].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
opal_parse("-> a = 1 {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:block, [:lasgn, :a, [:int, 1]]]]]
opal_parse("-> a = 1, b = 2 {}")[4][1].should == [:masgn, [:array, [:lasgn, :a], [:lasgn, :b], [:block, [:lasgn, :a, [:int, 1]], [:lasgn, :b, [:int, 2]]]]]
end

it "parses block args" do
opal_parse("-> &a {}")[2].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
opal_parse("-> &a {}")[4][1].should == [:masgn, [:array, [:block_pass, [:lasgn, :a]]]]
end
end

describe "with body statements" do
it "should be nil when no statements given" do
opal_parse("-> {}")[3].should == nil
opal_parse("-> {}")[4][2].should == nil
end

it "should be the single sexp when given one statement" do
opal_parse("-> { 42 }")[3].should == [:int, 42]
opal_parse("-> { 42 }")[4][2].should == [:int, 42]
end

it "should wrap multiple statements into a s(:block)" do
opal_parse("-> { 42; 3.142 }")[3].should == [:block, [:int, 42], [:float, 3.142]]
opal_parse("-> { 42; 3.142 }")[4][2].should == [:block, [:int, 42], [:float, 3.142]]
end
end
end
2 changes: 1 addition & 1 deletion spec/parser/str_spec.rb
Expand Up @@ -86,7 +86,7 @@
end

it "correctly parses block braces within interpolations" do
opal_parse('%Q{#{each { nil } }}').should == [:dstr, "", [:evstr, [:iter, [:call, nil, :each, [:arglist]], nil, [:nil]]]]
opal_parse('%Q{#{each { nil } }}').should == [:dstr, "", [:evstr, [:call, nil, :each, [:arglist], [:iter, nil, [:nil]]]]]
end

it "parses other Qstrings within interpolations" do
Expand Down
4 changes: 2 additions & 2 deletions spec/parser/xstr_spec.rb
Expand Up @@ -29,7 +29,7 @@
end

it "correctly parses block braces within interpolations" do
opal_parse('`#{ each { nil } }`').should == [:dxstr, "", [:evstr, [:iter, [:call, nil, :each, [:arglist]], nil, [:nil]]]]
opal_parse('`#{ each { nil } }`').should == [:dxstr, "", [:evstr, [:call, nil, :each, [:arglist], [:iter, nil, [:nil]]]]]
end

it "parses xstrings within interpolations" do
Expand Down Expand Up @@ -96,7 +96,7 @@
end

it "correctly parses block braces within interpolations" do
opal_parse('%x{#{each { nil } }}').should == [:dxstr, "", [:evstr, [:iter, [:call, nil, :each, [:arglist]], nil, [:nil]]]]
opal_parse('%x{#{each { nil } }}').should == [:dxstr, "", [:evstr, [:call, nil, :each, [:arglist], [:iter, nil, [:nil]]]]]
end

it "parses other Xstrings within interpolations" do
Expand Down

0 comments on commit bfad53f

Please sign in to comment.