#!/usr/bin/perl package Blondie::Backend::C; use base qw/Blondie::Runtime Blondie::Reducer::DynamicScoping/; use strict; use warnings; use UNIVERSAL::require; use Blondie::TypeSafe (); use Blondie::Backend::C::Builtins; sub run { my $self = shift; my $prog = shift; my $c = $self->compile($prog); my $type_annotated = $self->annotate($c); my $c_code = $self->emit($type_annotated); my $main = $self->bind($c_code); $main->(); } sub annotator_class { "Blondie::TypeSafe::Annotator" } sub annotator { my $self = shift; #$self->annotator_class->require || die $UNIVERSAL::require::ERROR; $self->annotator_class->new; } sub annotate { my $self = shift; $self->annotator->annotate($self, @_); } sub emitter_class { "Blondie::Backend::C::Emitter" } sub emitter { my $self = shift; $self->emitter_class->require || die $UNIVERSAL::require::ERROR; $self->emitter_class->new; } sub emit { my $self = shift; $self->emitter->emit(@_); } my %cache; sub bind { my $self = shift; my $c_code = shift; my $digest = Digest->new("SHA-1"); $digest->add($c_code); my $sha1 = $digest->digest; $cache{$sha1} ||= $self->generate_inline_c($c_code); } my $i; sub generate_inline_c { my $self = shift; my $c_code = shift; my %table = ( IV => "int", PV => "char *", ); $c_code =~ s/^([GIP]V) b_main/$table{$1} b_main/m; $c_code =~ s/([GIP]V)/blondie_$1/g; $c_code =~ s/int main \(\) {.*?}//; my $func = eval sprintf <<'BIND', __PACKAGE__, ++$i; package %s::inline_bindings::%d; use Inline C => Config => LIBS => "-lgc"; # http://www.hpl.hp.com/personal/Hans_Boehm/gc/ Inline->bind(C => $c_code); # marble losing routine \&b_main; BIND die $@ if $@; return $func; } sub compile_to_c { my $self = shift; my $compiled = $self->compile(@_); warn "compiled: $compiled"; my $safe = $self->annotate($compiled); $self->emit($safe); } sub provides { my $self = shift; my $node = shift; Blondie::Backend::C::Builtins->find($node->digest || return); } sub cast_node_type { my $self = shift; my $node = shift; my $from = shift->type; my $to = shift->type; Blondie::TypeSafe::Annotation->new( type => $to, struct_equiv => Blondie::App->new( Blondie::TypeSafe::Annotation->new( type => [$from => $to], struct_equiv => Blondie::Val->new( Blondie::TypeSafe::Annotation->new( type => [$from => $to], struct_equiv => Blondie::Backend::C::Prim->new( arity => 1, body => "type_convert_${from}_${to}", type => [$from => $to], ), ), ), ), (ref $node)->new( %$node, orig => Blondie::Val->new($node->orig), ), ), orig => $node->orig, ); } __PACKAGE__; __END__ =pod =head1 NAME Blondie::Backend::C - =head1 SYNOPSIS use Blondie::Backend::C; =head1 DESCRIPTION =cut