C-TinyCompiler

 view release on metacpan or  search on metacpan

lib/C/TinyCompiler.pm  view on Meta::CPAN

If you have a compiler error, line numbers will be meaningless if you do not
tell the compiler the line on which the code is run. To do this properly, use
L</line_number>, discussed below.

working here - note that warnings are not issued for changing code values after
the compilation phase, but such changes can have no effect.

=cut

# Valid locations are defined in %is_valid_location, created near the
# constructor.

sub code :lvalue {
	my ($self, $location) = @_;
	# Canonicalize the location:
	$location = ucfirst lc $location;
	
	# Make sure they supplied a meaningful location:
	croak("Unknown location $location; must be one of "
		. join(', ', keys %is_valid_location))
			unless exists $is_valid_location{$location};
	
	$self->{$location};
}

=head2 line_number

Build a line number directive for you. Use like so:

 $context->code('Body') .= C::TinyCompiler::line_number(__LINE__) . q{
     void test_func (void) {
         printf("Success!\n");
     }
 };

Suppose you have an error in your code and did not use this (or some other
means) for indicating your line numbers. The offending code could be

 $context->code('Body') .= q{
     void test_func (void {
         printf("Success!\n");
     }
 };

which, you will notice, forgets to close the parenthesis in the function
definition. This will raise an error that would look like this:

 Unable to compile at Body line 2: parameter declared as void

Although it tells you the section in which the error occurred, if you have a
complex script that adds code in many places, you may have no idea where to find
offending addition in your Perl code. Fortunately, C (and Perl) allows
you to give hints to the compiler using a C<#line> directive, which is made even
easier with this function. Without C<line_number>, you would say something like:

 $context->code('Body') .= "\n#line " . (__LINE__+1) . ' "' . __FILE__ . q{"
     ... code goes here ...
 };

and then your error reporting would say where the error occurred with respect to
the line in your script. That formula is long-winded and error prone, so you can
use this useful bit of shorthand instead:

 $context->code('Body') .= C::TinyCompiler::line_number(__LINE__) . q{
     ... code goes here ...
 };

Still not awesome, but at least a little better.

=cut

sub line_number {
	my ($line) = @_;
	# The line needs to be incremented by one for the bookkeeping to work
	$line++;
	# Get the source filename using caller()
	my (undef, $filename) = caller;
	# Escape backslashes:
	$filename =~ s/\\/\\\\/g;
	return "\n#line $line \"$filename\"";
}

=head2 apply_packages

Adds the given packages to this compiler context. The names should be the name
of the Perl package that has the functions expected by the C::TinyCompiler
package mechanisms:

 $context->apply_packages qw(C::TinyCompiler::Perl::SV C::TinyCompiler::Perl::AV);

The C<C::TinyCompiler> is optional, so this is equivalent to:

 $context->apply_packages qw(::Perl::SV ::Perl::AV);

Options are package-specific strings and should be specified after the
package name and enclosed by parentheses:

 $context->apply_packages qw(::Perl::SV(most) ::Perl::AV(basic))

You can call this function multiple times with different package names. However,
a package will only be applied once, even if you specify different package
options. Thus, the following will not work:

 $context->apply_packages '::Perl::SV(basic)';
 $context->apply_packages '::Perl::SV(refs)';

Instead, you should combine these options like so:

 $context->apply_packages '::Perl::SV(basic, refs)';

B<Note> that you can put spaces between the package name, the parentheses, and
the comma-delimited options, but C<qw()> will not do what you mean in that case.
In other words, this could trip you up:

 $context->apply_packages qw( ::Perl::SV(basic, refs) );

and it will issue a warning resembling this:

 Error: right parenthesis expected in package specification '::Perl::SV(basic,'

Again, these are OK:



( run in 0.558 second using v1.01-cache-2.11-cpan-bbcb1afb8fc )