C::TinyCompiler::package - base module for C::TinyCompiler packages
Here's a skeleton module for something that is meant to be a drop-in, ostensibly light-weight replacement for some big package called (generically) C::TinyCompiler::BigPackage.
package My::C::TinyCompiler::BigPackage; use parent 'C::TinyCompiler::package'; ### Overload the following, as appropriate ### # Called as soon as the package is applied: sub apply { my ($package, $compiler_state, @options) = @_; # Add to the Head section $compiler_state->code('Head') .= C::TinyCompiler::line_number(__LINE__) . q{ /* BEGIN My::C::TinyCompiler::BigPackage Head */ void my_func(void); #line 1 "whatever comes after My::C::TinyCompiler::BigPackage in the Head" }; # Add to the code section $compiler_state->code('Body') .= C::TinyCompiler::line_number(__LINE__) . q{ /* BEGIN My::C::TinyCompiler::BigPackage Body */ void my_func(void) { printf("You called my_func!"); } #line 1 "whatever comes after My::C::TinyCompiler::BigPackage in the Body" }; } # Check for known bad interactions and (hopefully) respond gracefully sub conflicts_with { my ($package, $state, @packages) = @_; # Can't respond gracefully here: croak('My::C::TinyCompiler::BigPackage cannot be used in the same context as C::TinyCompiler::Foo') if (grep {$_ eq 'C::TinyCompiler::Foo'} @packages); # Otherwise, we only conflict with C::TinyCompiler::BigPackage, so return unless that's # present return 0 unless grep {$_ eq 'C::TinyCompiler::BigPackage'} @packages; # If this package is being installed, it won't yet be registered as # applied; returning 1 (conflicting) will prevent it from being applied return 1 unless $state->is_package_applied($package); # If we're here, we can conclude that (1) this package has been applied and # (2) C::TinyCompiler::BigPackage is about to be applied. Retract this package and # return 0, indicating that we have not problem with C::TinyCompiler::BigPackage: $state->code('Head') =~ s{/\* BEGIN $package Head.*"whatever comes after $package in the Head"}{}s; $state->code('Body') =~ s{/\* BEGIN $package Body.*"whatever comes after $package in the Body"}{}s; $state->block_package($package); return 0; } # If you load any shared libraries, this is your chance to add those # functions to the compiler state: sub apply_symbols { my ($package, $state, @options) = @_; # add_symbols expects symbol_name => pointer pairs $state->add_symbols($package->get_my_symbols()); } # C-code source filtering, anyone? Applied after the C preprocessor # itself has run. sub preprocess { my ($package, $state, @options) = @_; $state->code('Body') =~ s/foo/bar/g; }
C::TinyCompiler Packages provide a means to easily integrate C code and libraries into a compiler context. They are akin to Perl modules, although applying them to a compiler state is a bit different compared to saying use My::Module in Perl. The most important similarity (in my mind) is that you can request a package multiple times without fear of trouble: each package is applied to a compiler context only once.
use My::Module
One of the first differences is that each package is asked if it conflicts with other packages that have been applied or are being applied. Although incompatibilities between packages should not arise very often, this mechanism provides a means for gracefully handling known conflicts between packages.
Another difference is that all packages are applied to the entire compiler context. The compiler context has no notion of lexical packages. (libtcc itself supports the notion of compiling multiple strings, much like compiling multiple files, so it may be possible to get lexical scoping of some sort using this mechanism. Patches welcome! :-)
Generally speaking, packages can accomplish these basic tasks:
If you want to interface an external library to a C::TinyCompiler context, you can use a package to dynamically load that library, add function declarations to the Head section, and add function pointers to the compiler's symbol table.
If you have a small but useful C library that is too small to distribute as an independent shared library, you can create a C::TinyCompiler package to add the function declarations and any preprocessor macros to the Head section, and the definitions to the Body section, much like C::TinyCompiler::StretchyBuffer. Or, you could scan the source code and generate functions dynamically based on content found in the code, as is done with C::TinyCompiler::Callable.
C::TinyCompiler::Callable
All code sections can be directly manipulated, so it is possible to use the preprocess method to redefine functions or rename function calls for selective overriding after having applied a package.
preprocess
The preprocess method allows for general text manipulation, so you can use it for generic source filtering. If you like using indendation as code blocks, you can create a C::TinyCompiler package to enable that for you. If you want to use the fat arrow => to mean something special in your code, you can write a C::TinyCompiler package to enable that for you. The sky is the limit.
=>
David Mertens, <dcmertens.perl at gmail.com>
<dcmertens.perl at gmail.com>
Please report any bugs or feature requests at the project's main github page: http://github.com/run4flat/perl-TCC/issues.
You can find documentation for this module with the perldoc command.
perldoc C::TinyCompiler::package
You can also look for information at:
The Github issue tracker (report bugs here)
http://github.com/run4flat/perl-TCC/issues
AnnoCPAN: Annotated CPAN documentation
http://annocpan.org/dist/C-TinyCompiler
CPAN Ratings
http://cpanratings.perl.org/d/C-TinyCompiler
Search CPAN
http://p3rl.org/C::TinyCompiler http://search.cpan.org/dist/C-TinyCompiler/
Code copyright 2012 Northwestern University. Documentation copyright 2012-2013 David Mertens.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.
To install C::TinyCompiler, copy and paste the appropriate command in to your terminal.
cpanm
cpanm C::TinyCompiler
CPAN shell
perl -MCPAN -e shell install C::TinyCompiler
For more information on module installation, please visit the detailed CPAN module installation guide.