package TestIntermediate; use strict; use warnings; use TestParser qw(parse_string); use Language::P::Intermediate::Generator; use Language::P::Intermediate::Transform; use Language::P::Opcodes; use Exporter 'import'; our @EXPORT_OK = qw(generate_main basic_blocks blocks_as_string generate_and_diff generate_tree_and_diff generate_ssa_and_diff); our %EXPORT_TAGS = ( all => \@EXPORT_OK, ); sub generate_main { my( $code ) = @_; my $parsetree = parse_string( $code ); my $gen = Language::P::Intermediate::Generator->new; my $segments = $gen->generate_bytecode( $parsetree ); return $segments; } sub generate_main_tree { my( $code ) = @_; my $parsetree = parse_string( $code ); my $gen = Language::P::Intermediate::Generator->new; my $segments = $gen->generate_bytecode( $parsetree ); my $trans = Language::P::Intermediate::Transform->new; my $trees = $trans->all_to_tree( $segments ); return $trees; } sub generate_main_ssa { my( $code ) = @_; my $parsetree = parse_string( $code ); my $gen = Language::P::Intermediate::Generator->new; my $segments = $gen->generate_bytecode( $parsetree ); my $trans = Language::P::Intermediate::Transform->new; my $trees = $trans->all_to_ssa( $segments ); return $trees; } my $op_map = \%Language::P::Opcodes::NUMBER_TO_NAME; my $op_attr = \%Language::P::Opcodes::OP_ATTRIBUTES; sub blocks_as_string { my( $segments ) = @_; my $str = ''; foreach my $segment ( @$segments ) { my $name = $segment->is_main ? 'main' : $segment->name || 'anoncode'; $str .= "# " . $name . "\n"; foreach my $block ( sort { $a->start_label cmp $b->start_label} @{$segment->basic_blocks} ) { foreach my $instr ( @{$block->bytecode} ) { $str .= $instr->as_string( $op_map, $op_attr ) } } } return $str; } sub generate_and_diff { my( $code, $assembly ) = @_; my $blocks = generate_main( $code ); my $asm_string = blocks_as_string( $blocks ); require Test::Differences; local $Test::Builder::Level = $Test::Builder::Level + 1; Test::Differences::eq_or_diff( $asm_string, $assembly ); } sub generate_tree_and_diff { my( $code, $assembly ) = @_; my $blocks = generate_main_tree( $code ); my $asm_string = blocks_as_string( $blocks ); require Test::Differences; local $Test::Builder::Level = $Test::Builder::Level + 1; Test::Differences::eq_or_diff( $asm_string, $assembly ); } sub generate_ssa_and_diff { my( $code, $assembly ) = @_; my $blocks = generate_main_ssa( $code ); my $asm_string = blocks_as_string( $blocks ); require Test::Differences; local $Test::Builder::Level = $Test::Builder::Level + 1; Test::Differences::eq_or_diff( $asm_string, $assembly ); } 1;