def precompile(compiler, scope)
expr = lambda { |e| e.kind_of?(CExpression) ? e : CExpression.new(nil, nil, e, e.type) }
if @bthen.kind_of? Goto or @bthen.kind_of? Break or @bthen.kind_of? Continue
if belse
t1 = @belse
@belse = nil
end
@bthen.precompile(compiler, scope)
@bthen = scope.statements.pop
elsif belse
t1 = @belse
t2 = @bthen
l2 = compiler.new_label('if_then')
@bthen = Goto.new(l2)
@belse = nil
l3 = compiler.new_label('if_end')
else
t1 = @bthen
l2 = compiler.new_label('if_end')
@bthen = Goto.new(l2)
@test = CExpression.negate(@test)
end
@test = expr[@test]
case @test.op
when :'&&'
l1 = compiler.new_label('if_nand')
If.new(CExpression.negate(@test.lexpr), Goto.new(l1)).precompile(compiler, scope)
@test = expr[@test.rexpr]
precompile(compiler, scope)
when :'||'
l1 = compiler.new_label('if_or')
If.new(expr[@test.lexpr], Goto.new(@bthen.target)).precompile(compiler, scope)
@test = expr[@test.rexpr]
precompile(compiler, scope)
else
@test = CExpression.precompile_inner(compiler, scope, @test)
t = @test.reduce(compiler)
if t.kind_of? ::Integer
if t == 0
Label.new(l1, nil).precompile(compiler, scope) if l1
t1.precompile(compiler, scope) if t1
Label.new(l2, nil).precompile(compiler, scope) if l2
Label.new(l3, nil).precompile(compiler, scope) if l3
else
scope.statements << @bthen
Label.new(l1, nil).precompile(compiler, scope) if l1
Label.new(l2, nil).precompile(compiler, scope) if l2
t2.precompile(compiler, scope) if t2
Label.new(l3, nil).precompile(compiler, scope) if l3
end
return
end
scope.statements << self
end
Label.new(l1, nil).precompile(compiler, scope) if l1
t1.precompile(compiler, scope) if t1
Goto.new(l3).precompile(compiler, scope) if l3
Label.new(l2, nil).precompile(compiler, scope) if l2
t2.precompile(compiler, scope) if t2
Label.new(l3, nil).precompile(compiler, scope) if l3
end