def precompile(compiler, scope)
var = Variable.new
var.storage = :register
var.name = compiler.new_label('switch')
var.type = @test.type
var.initializer = @test
CExpression.precompile_type(compiler, scope, var)
Declaration.new(var).precompile(compiler, scope)
@body = @body.precompile_make_block scope
@body.break_label = compiler.new_label('switch_break')
@body.precompile(compiler)
default = @body.break_label
walk = lambda { |blk|
blk.statements.each_with_index { |s, i|
case s
when Case
label = compiler.new_label('case')
if s.expr == 'default'
default = label
elsif s.exprup
If.new(CExpression.new(CExpression.new(var, :'>=', s.expr, BaseType.new(:int)), :'&&',
CExpression.new(var, :'<=', s.exprup, BaseType.new(:int)),
BaseType.new(:int)), Goto.new(label)).precompile(compiler, scope)
else
If.new(CExpression.new(var, :'==', s.expr, BaseType.new(:int)),
Goto.new(label)).precompile(compiler, scope)
end
blk.statements[i] = Label.new(label)
when Block
walk[s]
end
}
}
walk[@body]
Goto.new(default).precompile(compiler, scope)
scope.statements << @body
Label.new(@body.break_label).precompile(compiler, scope)
end