NAME
Data::Sah::Compiler::BaseCompiler - Base class for Sah compilers (Data::Sah::Compiler::*)
VERSION
version 0.05
ATTRIBUTES
main => OBJ
Reference to the main Data::Sah object.
expr_compiler => OBJ
Reference to expression compiler object. In the perl compiler, for example, this will be an instance of Language::Expr::Compiler::Perl object.
indent_character => STR (default: ' ')
Specify indent character used. Can be changed to a tab character, for example, but most compilers usually work with spaces.
METHODS
new() => OBJ
$c->compile(%args) => HASH
Compile schema into target language.
Arguments (*
denotes required arguments, subclass may introduce others):
data_name => STR (default: 'data')
A unique name. Will be used as default for variable names, etc. Should only be comprised of letters/numbers/underscores.
schema* => STR|ARRAY
The schema to use. Will be normalized by compiler, unless
schema_is_normalized
is set to true.schema_is_normalized => BOOL (default: 0)
If set to true, instruct the compiler not to normalize the input schema and assume it is already normalized.
allow_expr => BOOL (default: 1)
Whether to allow expressions. If false, will die when encountering expression during compilation. Usually set to false for security reason, to disallow complex expressions when schemas come from untrusted sources.
on_unhandled_attr => STR (default: 'die')
What to do when an attribute can't be handled by compiler (either it is an invalid attribute, or the compiler has not implemented it yet). Valid values include:
die
,warn
,ignore
.on_unhandled_clause => STR (default: 'die')
What to do when a clause can't be handled by compiler (either it is an invalid clause, or the compiler has not implemented it yet). Valid values include:
die
,warn
,ignore
.indent_level => INTT (default: 0)
Start at a specified indent level. Useful when generated code will be inserted into another code (e.g. inside
sub {}
where it is nice to be able to indent the inside code).
Compilation data
During compilation, compile() will call various hooks (listed below). The hooks will be passed compilation data ($cd
) which is a hashref containing various compilation state and result. Compilation data is written to this hashref instead of on the object's attributes to make it easy to do recursive compilation (compilation of subschemas).
Subclasses may add more data (see their documentation).
Keys which contain input data, compilation state, and others (many of these keys might exist only temporarily during certain phases of compilation and will no longer exist at the end of compilation, for example clause
will only exist during processing of a clause and will be seen by hooks like before_clause
and after_clause
, it will not be seen by before_all_clauses
or after_compile
):
args => HASH
Arguments given to
compile()
.compiler => OBJ
The compiler object.
outer_cd => HASH
If compilation is called from within another
compile()
, this will be set to the outer compilation's$cd
. The inner compilation will inherit some values from the outer, like list of types (th_map
) and function sets (fsh_map
).th_map => HASH
Mapping of fully-qualified type names like
int
and itsData::Sah::Compiler::*::TH::*
type handler object (or array, a normalized schema).fsh_map => HASH
Mapping of function set name like
core
and itsData::Sah::Compiler::*::FSH::*
handler object.schema => ARRAY
The current schema (normalized) being processed. Since schema can contain other schemas, there will be subcompilation and this value will not necessarily equal to
$cd->{args}{schema}
.th => OBJ
Current type handler.
type => STR
Current type name.
csets => ARRAY
All the clause sets. Each schema might have more than one clause set, due to processing base type's clause set.
cset => HASH
Current clause set being processed. Note that clauses are evaluated not strictly in cset order, but instead based on expression dependencies and priority.
cset_num => INT
Set to 0 for the first clause set, 1 for the second, and so on. Due to merging, we might process more than one clause set during compilation.
ucset => HASH
Short for "unprocessed clause set", a shallow copy of
cset
, keys will be removed from here as they are processed by clause handlers, remaining keys after processing the clause set means they are not recognized by hooks and thus constitutes an error.ucsets => ARRAY
All the
ucset
for each clause set.clause => STR
Current clause name.
cl_meta => HASH
Metadata information about the clause, from the clause definition. This include
prio
(priority),attrs
(list of attributes specific for this clause),allow_expr
(whether clause allows expression in its value), etc. SeeData::Sah::Type::$TYPENAME
for more information.cl_value => ANY
Clause value. Note: for putting in generated code, use
cl_term
.cl_term => STR
Clause value term. If clause value is a literal (
.is_expr
is false) then it is produced by passing clause value toliteral()
. Otherwise, it is produced by passing clause value toexpr()
.cl_is_expr => STR
A shortcut for
$cd->{cset}{"${clause}.is_expr"}
.cl_is_multi => STR
A shortcut for
$cd->{cset}{"${clause}.is_multi"}
.indent_level => INT
Current level of indent when printing result using
$c->line()
. 0 means unindented.all_expr_vars => ARRAY
All variables in all expressions in the current schema (and all of its subschemas). Used internally by compiler. For example (XXX syntax not not finalized):
# schema [array => {of=>'str1', min_len=>1, 'max_len=' => '$min_len*3'}, {def => { str1 => [str => {min_len=>6, 'max_len=' => '$min_len*2', check=>'substr($_,0,1) eq "a"'}], }}] all_expr_vars => ['schema:///csets/0/min_len', # or perhaps .../min_len/value 'schema://str1/csets/0/min_len']
This data can be used to order the compilation of clauses based on dependencies. In the above example,
min_len
needs to be evaluated beforemax_len
(especially ifmin_len
is an expression).
Keys which contain compilation result:
ccls => [HASH, ...]
Compiled clauses, collected during processing of schema's clauses. Each element will contain the compiled code in the target language, error message, and other information. At the end of processing, these will be joined together.
result
The final result. For most compilers, it will be string/text.
Return value
The compilation data will be returned as return value. Main result will be in the result
key. There is also ccls
, and subclasses may put additional results in other keys. Final usable result might need to be pieced together from these results, depending on your needs.
Hooks
By default this base compiler does not define any hooks; subclasses can define hooks to implement their compilation process. Each hook will be passed compilation data, and should modify or set the compilation data as needed. The hooks that compile() will call at various points, in calling order, are:
$c->before_compile($cd)
Called once at the beginning of compilation.
If hook sets $cd->{SKIP_COMPILE} to true then the whole compilation process will end (after_compile() will not even be called).
$c->before_all_clauses($cd)
Called before calling handler for any clauses.
$th->before_all_clauses($cd)
Called before calling handler for any clauses, after compiler's before_all_clauses().
$c->before_clause($cd)
Called for each clause, before calling the actual clause handler ($th->clause_NAME() or $th->clause).
If hook sets $cd->{SKIP_THIS_CLAUSE} to true then compilation for the clause will be skipped (including calling clause_NAME() and after_clause()). If $cd->{SKIP_REMAINING_CLAUSES} is set to true then compilation for the rest of the schema's clauses will be skipped (including current clause's clause_NAME() and after_clause()).
$th->before_clause($cd)
After compiler's before_clause() is called, type handler's before_clause() will also be called if available.
Input and output interpretation is the same as compiler's before_clause().
$th->clause_NAME($cd)
Called once for each clause. If hook sets $cd->{SKIP_REMAINING_CLAUSES} to true then compilation for the rest of the clauses to be skipped (including current clause's after_clause()).
$th->after_clause($cd)
Called for each clause, after calling the actual clause handler ($th->clause_NAME()).
If hook sets $cd->{SKIP_REMAINING_CLAUSES} to true then compilation for the rest of the clauses to be skipped.
$c->after_clause($cd)
Called for each clause, after calling the actual clause handler ($th->clause_NAME()).
Output interpretation is the same as $th->after_clause().
$th->after_all_clauses($cd)
Called after all clauses have been compiled, before compiler's after_all_clauses().
$c->after_all_clauses($cd)
Called after all clauses have been compiled.
$c->after_compile($cd)
Called at the very end before compiling process end.
$c->get_th
$c->get_fsh
AUTHOR
Steven Haryanto <stevenharyanto@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Steven Haryanto.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.