diff --git a/Makefile.am b/Makefile.am
index 90090f1b..e632d543 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,9 @@ path_src = src
path_test = test
# all source files will be run through hoxsl; see `applies' target
-apply_src := $(shell find "$(path_src)" "$(path_test)" -name '*.xsl')
+apply_src := $(shell find "$(path_src)" "$(path_test)" \
+ -name '*.xsl' \
+ -a \! -path "$(path_src)"/current/\* )
apply_dest := $(apply_src:%.xsl=%.xsl.apply)
# needed by test runner
diff --git a/README.md b/README.md
index 3a5dbdb4..6b562411 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,13 @@ TAME's core library, and [hoxsl](https://github.com/lovullo/hoxsl) was
developed as a supporting library.
+## "Current"
+The current state of the project as used in production is found in
+`src/current/`. The environment surrounding the development of this
+project resulted in a bit of a mess, which is being refactored into
+`src/` as it is touched. Documentation is virtually non-existent.
+
+
## License
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 6bd1f0c1..889824bc 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -21,7 +21,9 @@
path_src := ../src
path_tools := ../tools
-stylesheets := $(shell find "$(path_src)" -name '*.xsl')
+stylesheets := $(shell find "$(path_src)" \
+ -name '*.xsl' \
+ -a \! -path "$(path_src)"/current/\* )
stexi := $(stylesheets:.xsl=.texi)
info_TEXINFOS = tame.texi
diff --git a/src/current/.gitignore b/src/current/.gitignore
new file mode 100644
index 00000000..24600083
--- /dev/null
+++ b/src/current/.gitignore
@@ -0,0 +1 @@
+!Makefile
diff --git a/src/current/Makefile b/src/current/Makefile
new file mode 100644
index 00000000..dc6eb542
--- /dev/null
+++ b/src/current/Makefile
@@ -0,0 +1,8 @@
+
+.PHONY: dslc clean
+
+dslc:
+ $(MAKE) -C src/ dslc
+
+clean:
+ $(MAKE) -C src/ clean
diff --git a/src/current/c1map.xsl b/src/current/c1map.xsl
new file mode 100644
index 00000000..660fdf75
--- /dev/null
+++ b/src/current/c1map.xsl
@@ -0,0 +1,383 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [c1map] +
+
+
+
+
+ fatal: c1-map node not found
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [c1map] -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: missing required template argument `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: cannot have @dict on static mapping `
+
+ '
+
+
+
+
+
+
+ error: cannot have @default on static mapping `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [c1map] fatal: unexpected node
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
diff --git a/src/current/c1map/c1nodes.xsl b/src/current/c1map/c1nodes.xsl
new file mode 100644
index 00000000..da4470f2
--- /dev/null
+++ b/src/current/c1map/c1nodes.xsl
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+ =>
+
+
+
+
+
+
+
+
+
+ array(
+
+ )
+
+
+
+
+
+
+
+ =>
+
+
+
+
+ ,
+
+
+
+
+
+ '[
+
+ ]' =>
+
+ ,
+
+
+
+
+
+ '[
+
+ ]' =>
+
+ ,
+
+
+
+
+
+
+
+
+
diff --git a/src/current/c1map/render.xsl b/src/current/c1map/render.xsl
new file mode 100644
index 00000000..c782a35a
--- /dev/null
+++ b/src/current/c1map/render.xsl
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+
+
+
+ <?php
+
+
+
+ namespace lovullo\c1\interfaces\c1\contract\
+
+ ;
+
+
+ class
+
+ {
+
+
+ public function compose( $contract ) {
+
+ return array(
+
+
+
+
+ );
+
+ }
+
+
+ }
+
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+ '
+
+
+
+
+ $contract->checkDefaultValue( '
+
+ ',
+
+ )
+
+
+
+
+ null
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $contract->getValueByContext(
+
+
+
+
+
+ , '
+
+
+ '
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $contract->getValue( '
+
+ ', $contract->getValueIndex( '
+
+ ' )
+
+
+ ,
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: variable not within scope:
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $contract->iterateValues( '
+
+ ',
+ function( $contract ) {
+ return array(
+
+ );
+ }
+ )
+
+
+
+
+
+
+
+ '
+
+
+
+
+ >
+
+
+ '
+
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+ ( (
+ $contract->isTruthy(
+
+ )
+ ) ?
+
+
+
+ : null ),
+
+
+
+
+
+ [c1map] fatal: unexpected node during render:
+
+
+
+
+
diff --git a/src/current/c1map/transform.xsl b/src/current/c1map/transform.xsl
new file mode 100644
index 00000000..87936486
--- /dev/null
+++ b/src/current/c1map/transform.xsl
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ ucwords(strtolower(
+
+ ))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: unknown transformation `
+
+ ' for `
+
+ '
+
+
+
+
+
+
+ internal error: unexpected node for transformation:
+
+
+
+
+
+
diff --git a/src/current/c1map/valparse.xsl b/src/current/c1map/valparse.xsl
new file mode 100644
index 00000000..8c4ab1ff
--- /dev/null
+++ b/src/current/c1map/valparse.xsl
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+
+ ' .
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+ '
+
+
+
+
+ . '
+
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/calc.xsd b/src/current/calc.xsd
new file mode 100644
index 00000000..0030aa73
--- /dev/null
+++ b/src/current/calc.xsd
@@ -0,0 +1,883 @@
+
+
+
+
+
+
+
+
+ Generic name reference restriction, intended to be generic enough to
+ work with most systems (supporting both C-style and Lisp-style
+ identifiers).
+
+ The systems that implement this schema should perform their own, more
+ strict, type checks.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Valid value for constants.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Documentation for a specific element.
+
+ The documentation must not be sparse; please provide something
+ descriptive that will be useful to someone completely new to the code.
+
+
+
+
+
+
+
+
+
+
+
+
+ Single-character index variable
+
+
+
+
+
+
+
+
+
+
+
+
+ Symbol used to represent an entity when rendered.
+
+ The string should consist of TeX/LaTeX commands and should produce a
+ single symbol.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Abstract operator type used to classify elements as operators.
+
+ Operators are portions of the calculation that perform a portion of
+ the calculation. For example, a summation would classify as an
+ operation (operator), but value-of would not (as it is only
+ representing a value, but not performing a calculation).
+
+
+
+
+
+
+
+
+ Elements/attributes common to all operator types (see the operator
+ element for a description on what qualifies as an operator).
+
+ All operators may include child calculations. Furthermore, they may
+ be labeled and may have an identifier associated with their result.
+
+
+
+
+
+
+
+
+
+
+
+
+ Optional identifier with which the result of the calculation may be
+ referenced.
+
+
+
+
+
+
+ Optional description of a calculation. @label is used in place of
+ @desc to ensure that it is not confused with the otherwise required
+ @desc attribute.
+
+
+
+
+
+
+ @desc should be used to describe a value that is generated by a
+ calculation and should not otherwise be used (e.g. with
+ lv:sum/@generate)
+
+ This is different from @label, which provides a high-level
+ description of what the equation is doing. @desc describes what the
+ generated value is.
+
+
+
+
+
+
+ Allows for the definition of an index variable which will be
+ defined for all children of the operation.
+
+
+
+
+
+
+
+
+
+ Represents a summation (addition) of a set of values.
+
+ If @of is used, the equation defined by child elements will be
+ iterated using an index on the set provided by @of. If no equation is
+ given, all elements in the set identified by @of will be summed.
+
+ If @of is omitted, the result of each child element will be summed.
+
+ This operator should also be used for subtraction by summing negative
+ values.
+
+
+
+
+
+
+
+
+
+ Iterate over all values of this set. Must be a set.
+
+
+
+
+
+
+
+ Optional name of a set to generate from this expressions.
+
+ Generators are compatible only with @of and a sub-expression.
+
+
+
+
+
+
+
+ Symbol to use when typesetting the generator
+
+
+
+
+
+
+
+ Yield precision
+
+
+
+
+
+
+
+
+
+
+
+
+ Represents the product (multiplication) of a set of values.
+
+ If @of is used, the equation defined by child elements will be
+ iterated using an index on the set provided by @of. If no equation is
+ given, all elements in the set identified by @of will be multiplied.
+
+ If @of is omitted, the result of each child element will be
+ multiplied.
+
+ While this operator may also be used for division by multiplying by
+ the inverse of a number (n^-1), a limited quotient operator is
+ provided for clarity and convenience.
+
+
+
+
+
+
+
+
+
+ Iterate over all values of this set. Must be a set.
+
+
+
+
+
+
+
+ Optional name of a set to generate from this expressions.
+
+ Generators are compatible only with @of and a sub-expression.
+
+
+
+
+
+
+
+ Symbol to use when typesetting the generator
+
+
+
+
+
+
+
+ Dot product of any number of vectors
+
+
+
+
+
+
+
+ Yield precision
+
+
+
+
+
+
+
+
+
+
+
+
+ Represents the quotient (division) of two values.
+
+ This operator is to be thought of as a fraction: the numerator is
+ identified by the first child element and the denominator the second.
+
+ While the summation operator may also be used for division by
+ multiplying by the inverse of a number (n^-1), this limited operator
+ is provided for clarity and convenience.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Exponent; the first child node is the base, the second is the order.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Construct a list using the given element and an existing list
+
+ This is analogous to lisp's cons; the first argument is the car and
+ the second is the cdr.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Retrieve the first element of a list
+
+ Analogous to lisp's car.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Return the list without its first element
+
+ If the list contains only one element, then an empty list will be
+ returned. Analogous to lisp's cdr.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Retrieves the length of a vector
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Denotes a function application.
+
+ The result of the function identified by @name will be used in
+ place of the call. The application may optionally accept an
+ argument list (if the function accepts arguments).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the function to apply
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Represents an argument to be applied to a function.
+
+
+
+
+
+
+
+
+
+
+ Name of the parameter to apply to the function
+
+
+
+
+
+
+
+
+
+ Recursively applies the current function.
+
+ All arguments are copied to the argument list of the function application unless overridden.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Converts the given value to an integer, rounding up if necessary (e.g. 0.1 => 1)
+
+
+
+
+
+
+
+
+
+ Value precision to consider for rounding.
+
+
+
+
+
+
+
+
+
+
+
+
+ Converts the given value to an integer, rounding down if necessary (e.g. 0.9 => 0)
+
+
+
+
+
+
+
+
+
+ Value precision to consider for rounding.
+
+
+
+
+
+
+
+
+
+
+
+ Creates a set out of its siblings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Outputs the result of the contained expression to the console and
+ returns its value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines a condition under which the expression will yield one if
+ true, otherwise will be strongly zero (zero even if
+ undefined)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ More flexible alternative to the @index attribute on elements; supports
+ calculations for determining the index
+
+
+
+
+
+
+
+
+
+
+
+
+ Returns the value associated with the given identifier.
+
+
+
+
+
+
+
+
+
+
+
+ An identifier for which the value should be retrieved
+
+
+
+
+
+
+ Allows for the definition of an index variable which will be
+ defined for all children of the operation.
+
+
+
+
+
+
+ Optional description of a calculation. @label is used in place of
+ @desc to ensure that it is not confused with the otherwise required
+ @desc attribute.
+
+
+
+
+
+
+
+
+
+ Returns @value. This element simply enforces documentation and prevents
+ the use of magic values.
+
+
+
+
+
+
+
+
+
+
+
+ Value of constant (must be within the domain of its @type)
+
+
+
+
+
+
+ Type (domain) of the constant (inferred when not provided)
+
+
+
+
+
+
+ Description of the value explaining its intent
+
+
+
+
+
+
+ Optional description of a calculation. @label is used in place of
+ @desc to ensure that it is not confused with the otherwise required
+ @desc attribute.
+
+
+
+
+
+
+
+
+
+ Represents a list of cases for a calculation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Optional description of the case
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Optional description of the case
+
+
+
+
+
+
+
+
+
+
+ Optional description of the case set
+
+
+
+
+
+
+
+
+
+ Declares variables visible within the let block.
+
+ This exists as a means of assignment for re-using values.
+
+
+
+
+
+
+
+
+ Declares a list of values to define for this block
+
+
+
+
+
+
+
+
+
+ Declares a value that will remain in scope for the let block
+
+
+
+
+
+
+
+
+
+
+ Variable name
+
+
+
+
+
+
+
+ Variable datatype
+
+
+
+
+
+
+
+
+ Vector/matrix; if omitted, implicitly scalar.
+
+
+
+
+
+
+
+ Describe the purpose of the value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Represents every element that can be used to perform a calculation.
+ Implementors may use this group to accept any type of calculation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Root calculation node; this should be the entry point for any type of
+ calculation. This helps to ensure that certain nodes are only used at
+ the beginning of a calculation (such as cases).
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compile.xsl b/src/current/compile.xsl
new file mode 100644
index 00000000..2e8d561f
--- /dev/null
+++ b/src/current/compile.xsl
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! preprocessor error:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fatal: source file is invalid: unexpected node
+
+
+
+
+
diff --git a/src/current/compiler/fragments.xsl b/src/current/compiler/fragments.xsl
new file mode 100644
index 00000000..8ea60245
--- /dev/null
+++ b/src/current/compiler/fragments.xsl
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [jsc] fatal: unknown symbol type for `
+
+ ':
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/js-calc.xsl b/src/current/compiler/js-calc.xsl
new file mode 100644
index 00000000..8594d4f7
--- /dev/null
+++ b/src/current/compiler/js-calc.xsl
@@ -0,0 +1,1141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+
+
+
+
+ yes
+
+
+
+
+
+
+
+ ( function() { var result =
+
+
+
+
+
+ ;
+ ( debug['
+
+ '] || ( debug['
+
+ '] = [] ) ).push( result );
+
+ return result;
+ } )()
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+ (
+
+ (
+
+ )
+
+
+ * (
+
+
+ *
+
+
+
+
+ )
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _$i$_
+
+
+
+
+
+ ( function() {
+
+
+ var sum = 0;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ consts['
+
+ ']
+
+
+
+ args['
+
+ ']
+
+
+
+
+
+
+ var G = [];
+
+
+
+ for ( var
+
+ in
+
+ ) {
+
+ var result = +(+(
+
+
+
+
+
+
+
+
+
+ [
+
+ ]
+
+
+ )).toFixed(
+
+ );
+
+
+
+ G.push( result );
+
+
+
+ sum
+
+ = +result;
+
+
+ }
+
+
+
+ args['
+
+ '] = G;
+
+
+ return sum;
+ } )()
+
+
+
+
+
+ ( function() {
+
+
+ var _$dlen$ = longerOf(
+
+
+ ,
+
+
+
+
+
+ );
+
+
+ var _$dsum$ = 0;
+
+
+ for ( var _$d$ = 0; _$d$ < _$dlen$; _$d$++ ) {
+ _$dsum$ +=
+
+
+
+ *
+
+
+ ( (
+
+ || [] )[ _$d$ ] || 0 )
+
+ ;
+ }
+
+ return _$dsum$;
+
+ } )()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ *
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+ Math.
+
+ ( +(
+
+ ).toFixed(
+
+ ) )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )[__$$i]
+
+
+
+
+
+
+
+
+
+
+
+
+
+ || 0
+
+
+
+
+
+
+
+
+
+
+
+ || 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ consts['
+
+ ']
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ consts['
+
+ ']
+
+
+
+
+
+
+
+ || 0
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ args['
+
+ ']
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ || 0
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ ||[])
+
+ [
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ args['
+
+ ']
+
+
+
+ ]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ]
+
+
+
+
+
+
+
+
+ (
+
+
+
+
+ || 0 )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+ Math.pow(
+
+ ,
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+ ( args
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+
+
+ *
+
+
+
+
+
+
+
+
+ ( function() {
+
+ return (
+ (
+
+
+ )
+
+
+
+ ) ? 1 : 0;
+ } )()
+
+
+
+
+
+
+
+
+ ==
+ !=
+ >
+ <
+ >=
+ <=
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ( function() {
+
+
+
+
+ else
+
+
+ if (
+
+
+
+ *
+
+
+
+
+ ) { return
+
+
+ ; }
+
+
+
+
+
+
+
+ else
+
+
+
+ if ( true )
+
+
+
+ { return
+
+ ; }
+
+
+ } )() || 0
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+
+ ,
+
+
+
+
+ ]
+
+
+
+
+
+
+
+
+ (function(){
+
+ var cdr = Array.prototype.slice.call(
+
+ , 0);
+ cdr.unshift(
+
+ );
+
+ return cdr;
+ })()
+
+
+
+
+ (
+
+ [0]||0)
+
+
+
+
+ .slice(1)
+
+
+
+
+
+ (
+
+ .length || 0 )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+
+ =
+
+ function(
+
+
+
+ ,
+
+
+
+
+ ) {
+
+
+ return
+
+ ;
+ } )
+
+
+ (
+
+
+ ,
+
+
+
+ (
+
+ )
+
+ )
+
+
+
+
+
+
+
+ func_
+
+
+
+
+
+ (function(){
+ var result =
+
+ ;
+
+
+ console.log(
+
+ '
+
+ ',
+
+
+ result );
+ return result;
+ })()
+
+
+
+
+
+ ( function () {
+ throw Error( "Unknown calculation:
+
+ " );
+ } )()
+
+
+
diff --git a/src/current/compiler/js.xsl b/src/current/compiler/js.xsl
new file mode 100644
index 00000000..55ea0299
--- /dev/null
+++ b/src/current/compiler/js.xsl
@@ -0,0 +1,1908 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ( function() {
+
+ var debug = {};
+ var consts = {};
+ var params = {};
+ var types = {};
+ var meta = {};
+
+
+
+
+
+
+
+
+ function rater( arglist, _canterm ) {
+ _canterm = ( _canterm == undefined ) ? true : !!_canterm;
+
+
+ debug = {};
+
+
+
+
+
+ consts['__DATE_YEAR__'] = ( new Date() ).getFullYear();
+
+
+ var args = Object.create( arglist );
+
+
+ var req_params = {};
+
+
+ init_defaults( args, params );
+
+
+
+ var classes = rater.classify( args, _canterm );
+
+ var genclasses = {};
+
+
+
+
+
+ rater.classify = function( args, _canterm ) {
+ _canterm = ( _canterm == undefined ) ? true : !!_canterm;
+
+
+ consts['__DATE_YEAR__'] = ( new Date() ).getFullYear();
+
+
+ var classes = {}, genclasses = {};
+
+
+ var req_params = {};
+
+
+
+ return classes;
+ };
+
+
+ rater.classify.fromMap = function( args_base, _canterm ) {
+ var ret = {};
+ rater.fromMap( args_base, function( args ) {
+ var classes = rater.classify( args, _canterm );
+
+
+ for ( var c in classes )
+ {
+ ret[ c ] = {
+ is: !!classes[ c ],
+ indexes: args[ rater.classify.classmap[ c ] ]
+ };
+ }
+
+ } );
+ return ret;
+ };
+
+
+
+
+
+
+ return {
+
+ premium: ( Math.round( args.___yield * 100 ) / 100 ),
+ classes: classes,
+ vars: args,
+ consts: consts,
+ reqParams: req_params,
+ debug: debug
+ };
+ }
+
+
+ rater.supplier = '
+
+ ';
+
+ rater.meta = meta;
+
+
+
+ rater.classify.classmap = {
+
+
+
+ };
+
+
+
+ rater.classify.desc = {
+
+ };
+
+
+
+
+ rater.knownFields = {
+
+
+ ,
+
+
+ '
+
+ ': true
+
+ }
+
+
+
+
+
+ return rater;
+ } )()
+
+
+
+
+
+
+
+
+
+ ,
+
+
+ '
+
+ ':'
+
+ '
+
+
+
+
+
+
+
+
+
+ ,
+
+
+ '
+
+ ':'
+
+
+ '
+
+
+
+
+
+
+
+ params['
+
+ '] = {
+
+
+ type: '
+
+ ',
+
+ 'default': '
+
+ ',
+
+ required:
+
+
+ };
+
+
+
+
+
+
+ types['
+
+ '] = {
+
+
+ type: '
+
+ ',
+
+
+ values: {
+
+
+ ,
+
+
+
+
+ }
+
+ };
+
+
+
+
+
+
+ types['
+
+ '] = {
+
+
+ type: '
+
+ ',
+
+
+ values: {
+
+
+ ,
+
+
+
+
+ }
+
+ };
+
+
+
+
+ types['
+
+ '] = {
+
+
+ type: '
+
+ ',
+
+ values:{}
+
+ };
+
+
+
+
+
+ [lvc] Unhandled typedef:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+ ': true
+
+
+
+
+
+ consts['
+
+ '] = [
+
+
+
+
+ ,
+
+
+ [
+
+
+ ,
+
+
+
+
+ ]
+
+
+
+
+
+ ,
+
+
+
+
+
+ ];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ gen
+
+
+ classes['
+
+ '] = (function(){var result,tmp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ args['
+
+ ']
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tmp = true;
+
+
+
+
+ tmp = false;
+
+
+
+
+
+
+
+
+
+
+ = 1;
+
+
+
+
+ = 0;
+
+
+
+
+
+
+ return tmp;})();
+
+
+
+ if ( _canterm &&
+
+
+ gen
+
+ classes['
+
+ '] ) throw Error( '
+
+ ' );
+
+
+
+
+
+
+
+
+
+
+ =
+
+ [0];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tmp =
+
+
+
+
+
+ _cassume
+
+
+
+ args['
+
+ ']
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ stov(
+
+ , ( (
+
+
+ || [] ).length || 1 ) )
+
+
+
+
+
+
+
+
+
+ (function(){
+
+ var
+
+ ;
+
+
+
+
+
+ ; return
+
+
+
+ anyValue(
+
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [jsc] !!! TODO: bad classification match: '
+
+
+
+
+
+ '
+
+
+ [jsc] warning: static classification match '
+
+ ' in
+
+ ; use calculation predicate or constant instead
+
+
+
+ '
+
+
+
+
+
+ function( val ) {
+ return /
+
+ /.test( val );
+ }
+
+
+
+ function( val, __$$i ) {
+ return (
+
+
+ &&
+
+
+ ( val
+
+ )
+
+ );
+ }
+
+
+
+
+
+
+
+ , (
+
+ || (
+
+ = [] ) ),
+
+
+
+
+ true
+
+
+ false
+
+
+
+ ,
+
+
+ false
+
+
+ true
+
+
+
+
+ ,"
+
+ "
+
+
+ )
+
+
+
+ })()
+
+
+ ;
+
+ ( debug['
+
+ '] || ( debug['
+
+ '] = [] ) ).push( tmp );
+
+
+ result =
+
+
+
+ result
+
+ tmp;
+
+
+
+ tmp;
+
+
+
+
+
+
+
+ args['
+
+
+
+
+
+
+
+
+
+
+
+ ']
+
+
+
+
+
+ function( val ) {
+ return ( typeof +val === 'number' )
+ &&
+
+ ( Math.ceil( val ) >= Math.floor( val ) )
+ ;
+ }
+
+
+
+
+
+ function( val ) {
+ return ( typeof +val === 'number' )
+ &&
+ ( Math.floor( val ) === Math.ceil( val ) )
+ ;
+ }
+
+
+
+
+
+ function( val ) {
+ return ( val === '' )
+ || ( val === undefined ) || ( val === null )
+ ;
+ }
+
+
+
+
+
+ function( val ) {
+ throw Error( 'CRITICAL: Unhandled base type:
+
+ ' );
+ }
+
+
+
+
+ types['
+
+ '].values
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ function
+
+
+
+ ( args
+
+
+
+ ,
+
+
+
+ ) {
+
+ return (
+
+
+ );
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+
+
+ args['
+
+ ']
+
+
+
+
+ =
+
+ ( function rate_
+
+
+ () {
+
+ var predmatch = (
+
+ );
+
+
+ consts._CMATCH_ =
+
+ ;
+
+
+ return (+(
+
+
+ )).toFixed(
+
+ ) * predmatch; } )()
+
+ ;
+
+
+
+
+ (
+
+
+
+
+
+
+
+ &&
+
+
+
+
+ !
+
+
+
+
+
+ gen
+
+
+ classes['
+
+ ']
+
+
+
+
+
+ true
+
+
+ )
+
+
+
+
+
+
+
+ cmatch( [
+
+
+ ,
+
+
+ args['
+
+
+
+
+ ']
+
+ ], [
+
+
+ ,
+
+
+ args['
+
+
+
+
+ ']
+
+ ] )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ___$$
+
+ $$
+
+
+
+
+
+
+
+
+
+
+
+
+ meta['
+
+ '] =
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ param.length )
+ {
+ var sval = ( scalar ) ? anyPredicate( values, param[0] ) : null;
+ if ( typeof sval === 'function' )
+ {
+ // pass the scalar value to the function
+ sval = values[0]( param[0] );
+ }
+
+ // XXX: review the algorithm; this is a mess
+ for ( var k = param.length, l = store.length; k < l; k++ )
+ {
+ // note that this has the same effect as initializing (in the
+ // case of a scalar) the scalar to the length of the store
+ var v = +(
+ ( returnOrReduceOr( store[ k ], clear )
+ || ( !clear && ( scalar && sval ) )
+ )
+ && ( !clear || ( scalar && sval ) )
+ );
+
+ store[ k ] = ( scalar )
+ ? v
+ : [ v ];
+
+ found = ( found || !!v );
+ }
+ }
+
+ return found;
+ }
+
+
+ function anyPredicate( preds, value, index )
+ {
+ for ( var i in preds )
+ {
+ var p = preds[ i ];
+
+ if ( ( typeof p === 'function' )
+ && p( value, index )
+ )
+ {
+ return true;
+ }
+ // lazy equality intentional
+ else if ( p == value )
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ function returnOrReduceOr( arr, c )
+ {
+ if ( arr === undefined )
+ {
+ return !!c;
+ }
+ else if ( !( arr.length ) )
+ {
+ return arr;
+ }
+
+ return reduce( arr, function( a, b )
+ {
+ return returnOrReduceOr( a, c ) || returnOrReduceOr( b, c );
+ } );
+ }
+
+
+ function returnOrReduceAnd( arr, c )
+ {
+ if ( arr === undefined )
+ {
+ return !!c;
+ }
+ else if ( !( arr.length ) )
+ {
+ return arr;
+ }
+
+ return reduce( arr, function( a, b )
+ {
+ return returnOrReduceAnd( a, c ) && returnOrReduceAnd( b, c );
+ } );
+ }
+
+
+ function deepClone( obj )
+ {
+ var objnew = [];
+
+ // if we were not given an object, then do nothing
+ if ( typeof obj !== 'object' )
+ {
+ return obj;
+ }
+
+ for ( var i in obj )
+ {
+ // deep-clone for matrices
+ objnew[ i ] = ( typeof obj[ i ] === 'object' )
+ ? deepClone( obj[ i ] )
+ : obj[ i ];
+ }
+
+ return objnew;
+ }
+
+
+ /**
+ * Converts a match set to an integer
+ *
+ * If the given set is an array, then return a sum of each of its boolean
+ * values (if any one is set, then it's 1); otherwise, cast the given
+ * value to a number, just in case it's not.
+ *
+ * This function does not check to ensure that the given set contains valid
+ * data.
+ *
+ * @param {*} match set to convert
+ *
+ * @return {number} 1 or 0
+ */
+ function matchSetToInt( match )
+ {
+ if ( Array.isArray( match ) )
+ {
+ return reduce( match, function( a, b )
+ {
+ return a + b;
+ } );
+ }
+
+ return +match;
+ }
+
+
+ function cmatch( match, nomatch )
+ {
+ var len = 0,
+ cmatch = [];
+
+ // the length of our set should be the length of the largest set (we
+ // will not know this until runtime)
+ for ( var i in match )
+ {
+ // note that this has the consequence of not matching on scalar-only
+ // classifications...is this what we want? If not, we need to
+ // document a proper solution.
+ if ( ( match[ i ] || [] ).length > len )
+ {
+ len = match[ i ].length;
+ }
+ }
+
+ for ( var i in nomatch )
+ {
+ if ( ( nomatch[ i ] || [] ).length > len )
+ {
+ len = nomatch[ i ].length;
+ }
+ }
+
+ while ( len-- )
+ {
+ var fail = false;
+
+ for ( var i in match )
+ {
+ // if we're dealing with a scalar, then it should be used for
+ // every index
+ var mdata = ( ( typeof match[ i ] !== 'object' )
+ ? match[ i ]
+ : ( match[ i ] || [] )[ len ]
+ );
+
+ if ( !( matchSetToInt( mdata ) ) )
+ {
+ fail = true;
+ }
+ }
+
+ // XXX duplicate code
+ for ( var i in nomatch )
+ {
+ // if we're dealing with a scalar, then it should be used for
+ // every index
+ var mdata = ( ( typeof nomatch[ i ] !== 'object' )
+ ? nomatch[ i ]
+ : ( nomatch[ i ] || [] )[ len ]
+ );
+
+ if ( matchSetToInt( mdata ) !== 0 )
+ {
+ fail = true;
+ }
+ }
+
+ cmatch[ len ] = ( fail ) ? 0 : 1;
+ }
+
+ return cmatch;
+ }
+
+
+ /**
+ * Return the length of the longest set
+ *
+ * Provide each set as its own argument.
+ *
+ * @return number length of longest set
+ */
+ function longerOf()
+ {
+ var i = arguments.length,
+ len = 0;
+ while ( i-- )
+ {
+ var thislen = arguments[ i ].length;
+
+ if ( thislen > len )
+ {
+ len = thislen;
+ }
+ }
+
+ return len;
+ }
+
+
+ /**
+ * Some browsers don't support Array.reduce(), and adding to the prototype
+ * causes problems since we cannot make it non-enumerable in those browsers
+ * due to broken Object.defineProperty implementations (IE8).
+ */
+ function reduce( arr, c )
+ {
+ var ret = arr[ 0 ],
+ i = 0, // skip first
+ l = arr.length;
+
+ while ( ++i < l )
+ {
+ ret = c( ret, arr[ i ] );
+ }
+
+ // note that this will have the effet of returning the first element if
+ // there are none/no more than 1
+ return ret;
+ }
+
+
+ /* scalar to vector */
+ function stov( s, n )
+ {
+ // already a vector
+ if ( typeof s === 'object' )
+ {
+ // if the length is only one, then we can pretend that it is a
+ // scalar (unless the requested length is one, in which case it is
+ // utterly pointless to continue)
+ if ( ( n === 1 ) || ( s.length !== 1 ) )
+ {
+ return s;
+ }
+
+ s = s[ 0 ];
+ }
+
+ var v = [];
+ for ( var i = 0; i < n; i++ )
+ {
+ v.push( s );
+ }
+
+ return v;
+ }
+
+
+ function argreplace( orig, value )
+ {
+ if ( !( typeof orig === 'object' ) )
+ {
+ return value;
+ }
+
+ // we have an object; recurse
+ for ( var i in orig )
+ {
+ return argreplace( orig[ i ], value );
+ }
+ }
+
+
+ function init_defaults( args, params )
+ {
+ for ( var param in params )
+ {
+ var val = params[ param ]['default'];
+ if ( !val )
+ {
+ continue;
+ }
+
+ args[ param ] = set_defaults( args[ param ], val );
+ }
+ }
+
+
+ function set_defaults( input, value )
+ {
+ // scalar
+ if ( !( typeof input === 'object' ) )
+ {
+ return ( input === '' || input === undefined ) ? value : input;
+ }
+
+ // otherwise, assume array
+ var i = input.length;
+ var ret = [];
+ while ( i-- ) {
+ ret[i] = ( input[i] === '' ) ? value : input[i];
+ }
+ return ret;
+ }
+]]>
+
+
+
+
diff --git a/src/current/compiler/linker.xsl b/src/current/compiler/linker.xsl
new file mode 100644
index 00000000..f6a04783
--- /dev/null
+++ b/src/current/compiler/linker.xsl
@@ -0,0 +1,1442 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cannot link
+
+ ; must link program
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ linking
+
+ ...
+
+
+
+
+
+
+
+
+ building dependency tree...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ resolving dependency tree...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ l:mark-class found for non-existing symbol
+
+ ; there is a bug in l:depgen-process-sym
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+ p -
+
+ s -
+
+ r -
+
+ [s::
+
+ ::s] [r::
+
+ ::r]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unresolved extern
+
+ (declared by `
+
+ ')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ could not resolve external symbol `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+ ambiguous external symbol `
+
+ '; resolution failed (found
+
+
+ ;
+
+
+
+ ); pulled in by:
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ symbol name is not unique: `
+
+ ' found in
+
+
+
+ and
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ depends upon
+
+ external
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ could not locate dependency list for
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ failed locating dependency symbol `
+
+ '
+ from package
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: unknown symbol for l:depgen-sym:
+
+
+
+
+
+
+
+
+
+
+
+
+ circular dependency
+
+ (
+
+ ):
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ compiling entry point...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ compiling exit...
+
+
+
+
+
+
+
+ compilation complete.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fatal: missing exit fragment:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking metadata...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking worksheet...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking classifier...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking global params...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking types...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking functions...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ** linking rater...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ linking
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ missing object code for symbol
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ could not locate package for exit-fragment:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generating input map...
+
+
+
+
+
+
+
+ missing object code for input map head or tail
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ generating return map...
+
+
+
+
+
+
+
+ missing object code for return map head or tail
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ could not locate symbol dependencies:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ map
+
+
+
+ is not a known
+
+ field for
+
+ ; ensure that it exists and is either used or has @keep set
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/linker/log.xsl b/src/current/compiler/linker/log.xsl
new file mode 100644
index 00000000..9c8db608
--- /dev/null
+++ b/src/current/compiler/linker/log.xsl
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ]
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ]
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ] warning:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ] error:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [
+
+ ] internal error:
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/map.xsl b/src/current/compiler/map.xsl
new file mode 100644
index 00000000..10d8c426
--- /dev/null
+++ b/src/current/compiler/map.xsl
@@ -0,0 +1,997 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fatal: program UI source XML not found
+
+
+
+
+
+
+ !!! Terminating due to errors.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ function( input, callback ) {
+ var output = {};
+
+
+
+
+
+
+
+
+
+
+ callback(output);
+ };
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ function ( input, callback ) {
+ var output = {};
+
+
+
+
+
+
+
+
+
+ callback(output);
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ output['
+
+ ']=
+
+
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [map] notice: `
+
+
+ ' has a destination of the same name; use lvm:pass instead
+
+
+
+
+ output['
+
+ ']=
+
+
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ input['
+
+ ']
+
+
+
+
+
+
+ set_defaults(
+
+ ,'
+
+ ')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ output['
+
+ ']='
+
+ ';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ output['
+
+ ']=
+
+
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+ '
+
+
+
+ (function(){
+ var ret=[];
+ var len=input['
+
+ '].length;
+
+ for(var _i=0;_i<len;_i++){
+ var
+
+ =_i;
+
+ ret[_i]=
+
+ ;
+ }
+
+ return ret;
+ })()
+
+
+
+ (function(){
+ var ret=[]; var tmp;
+
+
+ tmp=
+
+ ;
+
+ if(tmp&&tmp!=='0')ret.push(tmp);
+
+
+ return ret;
+ })()
+
+
+
+ [
+
+
+ ,
+
+
+
+
+ ]
+
+
+
+ '
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+ (function(oval){
+ var val = ( (oval||'').length ) ? oval : [oval];
+ var ret = [];
+
+
+ var curindex;
+
+
+ for ( var i = 0, l = val.length; i<l; i++ ){
+
+ curindex = i;
+
+
+
+ switch(''+val[i]){
+
+
+
+ default: ret.push(
+
+
+
+
+
+
+
+
+
+
+
+
+ ''+val[i]
+
+
+
+
+ );
+
+ }
+ }
+
+
+
+ return ret[0];
+
+
+
+ return ret;
+
+
+
+ })(input['
+
+ ']
+
+
+ [curindex]
+
+
+ )
+
+
+
+
+
+
+ input['
+
+ ']
+
+
+
+ [
+
+ ]
+
+
+
+ [curindex]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ case '
+
+ ':
+
+ break;
+
+
+
+
+
+
+
+
+
+
+
+
+ (function(){
+
+ var result=
+
+
+ +
+
+
+
+
+ ;
+
+ return (result === "") ? '
+
+ ' : result;
+ })()
+
+
+
+
+
+
+
+
+
+
+
+ ret.push('
+
+ ');
+
+
+
+
+
+
+
+
+
+
+ fatal: invalid map: unexpected node
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+ function
+
+ ( input, callback ) {
+
+ var prot = function() {};
+ prot.prototype = input;
+ callback( new prot() );
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ! [map warning] unmapped optional field:
+
+
+
+
+
+
+
+ !!! [map error] unmapped required field:
+
+
+
+
+
+
+
+
+
+
+
+ !!! [map error] unknown/unused destination identifier:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! [map error] unknown source field:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unknown node:
+
+
+
+
+
diff --git a/src/current/compiler/validate.xsl b/src/current/compiler/validate.xsl
new file mode 100644
index 00000000..91cfd03a
--- /dev/null
+++ b/src/current/compiler/validate.xsl
@@ -0,0 +1,771 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [validate] prohibited; skipping
+
+
+
+ ...
+
+
+
+
+
+ [validate] validating
+
+
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for application of
+
+ ()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+
+ ' is unknown for classification
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+
+ ' is unknown for classification
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is not used to classify
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ is
+
+
+
+ undefined
+
+
+
+ of type '
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal warning: unresolved param
+ dimension: `
+
+ '
+
+
+
+
+
+
+ Unexpected vector/matrix reference
+
+
+
+
+ (did you forget @index?)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ requires
+
+ indexes (use c:index) unless being
+ passed as a function argument
+
+
+
+
+
+
+
+
+
+
+
+ may only have
+
+ index(s)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Argument `
+
+ ' is unknown for function `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Expected type '
+
+ ' for
+
+ , but found '
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unknown classification '
+
+ ' referenced by
+
+
+
+
+
+
+
+
+
+
+
+
+ missing or empty @yields; see document dump
+
+
+
+
+
+
+
+
+
+
+
+
+ Cannot create generator '
+
+ '; generating expressions must contain both @of
+ and a sub-expression.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @desc required when creating generator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+ [
+
+ ]
+
+
+
+
+ @yields=
+
+
+
+
+ @name=
+
+
+
+ @label=
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/validate/domain.xsl b/src/current/compiler/validate/domain.xsl
new file mode 100644
index 00000000..0d84a8cf
--- /dev/null
+++ b/src/current/compiler/validate/domain.xsl
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: no domain symbol provided;
+ caller:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: unexpected node for lvv:domain-chk:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: no domain found for
+
+ /
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/validate/param.xsl b/src/current/compiler/validate/param.xsl
new file mode 100644
index 00000000..1d18d7a8
--- /dev/null
+++ b/src/current/compiler/validate/param.xsl
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '
+
+ ' is undefined for param
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: in limbo processing param `
+
+ ' @default
+
+
+
+
+
+
+
+ param `
+
+ ' @default of `
+
+ ' is not within its domain of
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/compiler/worksheet.xsl b/src/current/compiler/worksheet.xsl
new file mode 100644
index 00000000..9149ddd4
--- /dev/null
+++ b/src/current/compiler/worksheet.xsl
@@ -0,0 +1,543 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rater.worksheet =
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/doc/.gitignore b/src/current/doc/.gitignore
new file mode 100644
index 00000000..2fa45d09
--- /dev/null
+++ b/src/current/doc/.gitignore
@@ -0,0 +1,4 @@
+*.aux
+*.pdf
+*.log
+*.toc
diff --git a/src/current/doc/chapters/class.tex b/src/current/doc/chapters/class.tex
new file mode 100644
index 00000000..82a2f624
--- /dev/null
+++ b/src/current/doc/chapters/class.tex
@@ -0,0 +1,372 @@
+\chapter{Classification System}
+The classification system is one of the most powerful features of \lang,
+allowing precise control over the classification and conditional processing of
+large sets of data, whether it be external input or values generated from within
+\lang\ itself. Virtually every conditional calculation is best represented
+through use of the classification system.
+
+
+\section{Classification Matcher}
+Data classification is performed by the classification matcher (sometimes
+referred to simply as the ``matcher''). Put simply, it is a function (defined by
+\aref{cmatch}) that, given a vector of inputs, produces a boolean vector (which
+may itself contain boolean vectors) determining if the given input conforms to a
+set of stated rules. A set of rules operating on a set input vectors is
+collectively known as a \term{classification}. The system that performs matching
+based on classifications is referred to as a \term{classifier}.
+
+A single classification can be separated into a set of rules, often referred to
+as \term{matches} within the context of \lang. A single rule attempts to match
+on a vector of inputs.\footnote{Scalar inputs are a special condition defined in
+\sref{cmatch-scalar}.} A simple example of such a match is shown in
+\fref{cmatch-ex-single}.
+
+\begin{figure}[h]
+ $$
+ I = \left[
+ \begin{array}{c}
+ 1 \\ 3 \\ 4 \\ 1
+ \end{array}
+ \right]
+ \qquad
+ M = \left[
+ \begin{array}{c}
+ 1 \\ 4
+ \end{array}
+ \right]
+ \quad
+ \to
+ \quad
+ R = \left[
+ \begin{array}{c}
+ \top \\ \bot \\ \top \\ \top
+ \end{array}
+ \right].
+ $$
+
+ \caption{A simple classification match $M$ on input $I$ and its result vector
+ $R$.}
+ \label{f:cmatch-ex-single}
+\end{figure}
+
+In \fref{cmatch-ex-single}, the input vector $I$ is \term{matched} against the
+rule $M$. The output is a boolean result vector $R$ which can be summarized with
+the following rule:
+
+$$
+ R_n = \exists m\in M(m = I_n).
+$$
+\noindent
+In other words, $R_n$ is $\top$ if $I_n\in M$ and is $\bot$ if $I_n\notin M$.
+Under this definition, $M$ can be considered to be the \term{domain} under which
+a given input $I_n$ is considered to be valid (a \term{match}).
+
+We say that a classification rule \term{matches} if \emph{any} input matches.
+That is:
+
+$$
+ \left[\textrm{The rule $M$ matches input $I$}\right]
+ \iff
+ \top\in R
+$$
+\noindent
+Another way to think of this concept is the reduction of the result vector $R$
+using a logical OR. Alternatively, one could assert that:
+
+$$
+ \left[\textrm{The rule $M$ matches input $I$}\right]
+ \iff
+ \sum\limits_n R_n \geq 1, \qquad R \in \set{0,1},
+$$
+\noindent
+if an implementation were willing to use the sets \boolset and \set{1,0}
+interchangeably.\footnote{See \sref{cmatch-int}.}
+
+The following sections, however, serve to demonstrate that such a simple view of
+the classification system, while useful for an introductory demonstration, is
+not sufficient when considering the level of flexibility that is necessary to
+handle more complicated data (in particular, when $I$ is a
+matrix).\footnote{See $\Omega$-reductions, introduced in
+\asref{cmatch}{omega-reduce}.}
+
+%TODO: More example sections
+
+
+\subsection{Classification Match (cmatch) Algorithm}
+\label{a:cmatch}
+
+The classification match (``cmatch'') algorithm is used to determine if a given
+set of data matches a given set of classification criteria.
+
+Let $I$ be the vector of input values.\footnote{$I$ may be a matrix (a vector
+of vectors).} Let $M$ be the vector of predicates to match against $I$ such
+that a match will be considered successful if \emph{any} predicate is true.
+Since $I$ shall always be a vector of values---even if the vector contains only
+one element (see algorithm below for comments on scalar values)---$M$ should be
+a vector of one element if the desire is to match against a scalar value (rather
+than a vector of values). Let $c$ (clear) be a boolean value\footnote{$1$ or $0$
+when used within an integer context within the algorithm.} representing whether
+the results of this operation should be logically AND'd together with the
+prior cmatch result ($R'$ in the algorithm below); otherwise, the results will
+be OR'd (see step \ref{a:cmatch-c} below).
+
+Let $A\!\left(M,I,c,R'\right)$ (the ``algorithm'') be defined as:
+
+\begin{enumerate}
+ \item
+ Let $R$ be the result vector.
+
+ \item\label{a:cmatch-scalar}
+ If the given input vector $I$ is a scalar, it should be converted to a vector
+ of length 1 with the value of the single element being the original scalar
+ value of $I$---that is, let $s$ be the original scalar value of $I$; then: $I
+ = \left[ s \right]$. If $s$ is undefined, then an empty result vector should
+ be returned.
+
+ \item\label{a:cmatch:input-vectorize}
+ Step \ref{a:cmatch-scalar} should also be done to the match vector $M$,
+ yielding $M = \left[ s \right]$ where $s$ is the original scalar $M$. If $s$
+ is undefined, then it should be treated as if it were the integer
+ $0$.\footnote{Consistent with the behavior of the remainder of the DSL.}
+
+ \item
+ Step \ref{a:cmatch-scalar} should also be done to the prior result vector
+ $R'$, yielding $R = \left[ s \right]$ where $s$ is the original scalar $R'$.
+ This situation may result from recursing at step \ref{a:cmatch-mrecurse} when
+ $R'_k$ is a scalar. If $s$ is undefined, then $R'$ should be initialized to an
+ empty vector, implying a fresh match (no prior results).
+ \goodbreak
+
+ \item\label{a:cmatch-iter}
+ The length of the result vector $R$~($\#R$) shall be the larger of the length
+ of the input vector $I$~($\#I$) or the prior result vector $R'$~($\#R'$).
+ For each $I_k \in I$:
+
+ \begin{enumerate}
+ \item\label{a:cmatch-mrecurse}
+ If $I_k$ is a vector, recurse, beginning at step 1. Let $r =
+ A(M_k,I_k,c,R'_k)$.
+
+ \begin{align*}
+ u &= \left\{
+ \begin{array}{ll}
+ \bot & \textrm{if }\#R' > 0, \\
+ c & \textrm{otherwise.}
+ \end{array}
+ \right. \\
+ %
+ R_k &= \left\{
+ \begin{array}{ll}
+ r & \textrm{if $R'_k$ is a vector or undefined}, \\
+ \Omega(r,u) & \textrm{otherwise}.\footnotemark
+ \end{array}
+ \right.
+ \end{align*}
+
+ \footnotetext{\label{a:cmatch-order} If $R'_k$ is a scalar, we must ensure
+ consistency with step \ref{a:cmatch-c} to ensure that the algorithm is not
+ dependent on input or execution order. Note the use of $u$ in place of
+ $c$---this ensures that, if there are any $R'$, we are consistent with the
+ effects of step \ref{a:cmatch:fill} (but in reverse).}
+
+ Continue with the next $I$ at step \ref{a:cmatch-iter}.
+
+ \item
+ \label{a:cmatch:omega-reduce}
+ Otherwise, $I_k$ is a scalar. Let $t$ be a temporary (intermediate) scalar
+ such that $t = \exists m \in M m(I_k)$.
+
+ \item\label{a:cmatch-c}
+ Let $v = \Omega\left(R'_k,c\right)$ and let
+ $$
+ R_k = \left\{
+ \begin{array}{ll}
+ v \wedge t & c = \top, \\
+ v \vee t & c = \bot.
+ \end{array}
+ \right.,
+ $$
+
+ where\footnote{$\Omega$ is simply the recursive reduction of a vector using
+ a logical OR. This function exists to resolve the situation where $R'_k$ is
+ a vector of values when $I_k$ is a scalar, which will occur when $M_k$ is
+ scalar for any $k$ during one application of the cmatch algorithm and $M_k$
+ is a vector for another iteration, where $R'$ is the previous match using
+ scalars. Note also that $X$, according to the recursion rule, may only be
+ undefined on the first iteration (in effect initializing the value).}
+
+ $$
+ \Omega\left(X,u\right) = \left\{
+ \begin{array}{ll}
+ u & \textrm{if X is undefined,} \\
+ X & \textrm{if X is a scalar,} \\
+ \exists x\in X \Omega(x,u) & \textrm{otherwise.}
+ \end{array}
+ \right. \>
+ \mbox{
+ $X \in \left\{\textrm{undefined},\top,\bot\right\}$
+ or a vector.
+ }
+ $$
+ \end{enumerate}
+
+ \item\label{a:cmatch:fill}
+ Let $v = \Omega\left(R'_k,c\right) \wedge \neg c$. If $\#R' > \#I$,
+ $$
+ R_k = \left\{
+ \begin{array}{ll}
+ v & \exists n\in I(n\textrm{ is a scalar}), \\
+ \left[v\right] & \textrm{otherwise.}\footnotemark
+ \end{array}
+ \right.
+ k \in \left\{j : \#I \leq j < \#R' \right\}.
+ $$
+
+ \footnotetext{Note that step \ref{a:cmatch:fill} will produce results
+ inconsistent with the recursive step \ref{a:cmatch-mrecurse} if there exists
+ an $I_n$ that is a matrix; this algorithm is not designed to handle such
+ scenarios.}
+\end{enumerate}
+
+Given a set of classification criteria $C$ such that $C_k = M$ for some integer
+$k$ and some application of $A$, and a vectorized clear flag $c$ such that $c_k$
+is associated with $C_k$, the final result $F(\#C-1)$ shall be defined as
+
+$$
+ F(k) = \left\{
+ \begin{array}{ll}
+ A\left(C_k,I_k,c_k\right) & \textrm{k = 0,} \\
+ A\bigl(C_k,I_k,c_k,F\!\left(k-1\right)\bigr) & \textrm{otherwise.}
+ \end{array}
+ \right.
+$$
+
+The order of recursion on $F$ need not be right-to-left; $A$ is defined such
+that it will produce the same result when applied in any order. This is
+necessary since the input may be provided in any order.\footnote{Ibid,
+\ref{a:cmatch-order}.}
+
+\subsubsection{Boolean Classification Match}
+\label{s:cmatch-boolean}
+A scalar boolean classification match $b$ may be obtained simply as $b =
+\Omega\left(F,\bot\right)$, where $F$ and $\Omega$ are defined in the algorithm
+above. Consequently, note that an empty result set $F$ will be treated as
+$\bot$, since index $0$ will be undefined.
+
+\subsubsection{Match Vector}
+$M$ is defined to be a vector of predicates which serve to {\sl match} against a
+vector of input values. Most frequently, predicates will likely be against scalar
+values. In such a case, an implementation may choose to forego function
+application for performance reasons and instead match directly against the
+scalar value. However, this document will consider scalar matches in the context
+of predicates as functions. As such, if $M$ is a matrix, then the results are
+implementation-defined (since the value does not make sense within the algorithm
+as defined).
+
+\subsubsection{Integer Results}
+\label{s:cmatch-int}
+$A$ defines $R$ to be a vector/matrix of boolean values. However, it may be
+useful to use the cmatch results in calculations; as such, implementations that
+make use of or produce cmatch results are required to do one or both of the
+following where $b$ is a boolean scalar:
+
+\begin{enumerate}
+ \item
+ Implicitly consider $b$ to be $\textrm{int}\!\left(b\right)$ when used in
+ calculations, and/or
+
+ \item
+ Perform the implicit conversion before $R$ is returned from $A$,
+\end{enumerate}
+
+where the function {\sl int} is defined as
+
+$$
+ \textrm{int}(b) = \left\{
+ \begin{array}{ll}
+ 1 & \textrm{if }b = \top, \\
+ 0 & \textrm{if }b = \bot.
+ \end{array}
+ \right.\qquad
+ b \in \left\{\top,\bot\right\}.
+$$
+
+
+\subsection{Scalar Classification Matches}
+\label{s:cmatch-scalar}
+Implementations may find it convenient to support scalar inputs and scalar
+classification matches to represent matching ``all'' indexes of a vector.
+\aref{cmatch} defines both a classification match ($R$, and consequently $F$)
+and an input ($I$) to be a vector, which is generally sufficient. However, in
+the case where the number of indexes of the inputs and results of other matches
+may be arbitrary, it may be useful to apply a certain classification across all
+indexes, which cannot be done when $c = \top$ using \aref{cmatch}.
+
+The onus of such a feature is on the implementation---it should flag such input
+($I$) as a scalar, which is necessary since $I$ is unconditionally converted to
+a vector by step \asref{cmatch}{input-vectorize}. If an implementation decides
+to support scalar classification matches, \emph{it must conform to this
+section}. Let such a scalar flag be denoted $s_k \inbool$ respective to input
+$I_k$. Handling of both $F$ and $I$ is discussed in the sections that follow.
+
+\subsubsection{Mixing Scalar And Vectorized Inputs}
+\label{s:cmatch-scalar-mixed}
+Under the condition that $\exists v\in s(v=\top)$, the compiler must:
+
+\begingroup
+ % this definition is local to this group
+ \def\siset{k \in\set{j : s_j = \top}}
+
+ \begin{enumerate}
+ \item
+ Reorder inputs $I$ such that each scalar input $I_k, \siset$ be applied
+ after all non-scalar inputs have been matched using \aref{cmatch}.
+ \begin{enumerate}
+ \item
+ Consequently (and contrary to what was mentioned in \aref{cmatch}),
+ application order of $A$ with respect to inputs $I$ \emph{does} in fact
+ matter and implementations should ensure that this restriction holds
+ during runtime.
+ \end{enumerate}
+
+ \item
+ Before application of a scalar input, the scalar $I_k$ should be vectorized
+ according to the following rule:
+
+ $$
+ I'_{k,l} = I_k,
+ \qquad \siset,
+ \; 0 \leq l < \#R',
+ $$
+
+ where $R'$ is the value immediately before the application of $I_k$ as
+ defined in \aref{cmatch}.
+
+ \item
+ Application of \aref{cmatch} should then proceed as normal, using $I'$ in
+ place of $I$.
+ \end{enumerate}
+\endgroup
+
+\subsubsection{Converting Vectorized Match To Scalar}
+As defined by \aref{cmatch}, the result $R$ will always be a vector. An
+implementation may \emph{only} convert a vectorized match to a scalar using the
+method defined in this section under the condition that $\forall v\in
+s(v=\top)$; otherwise, there will be a loss of data (due to the expansion rules
+defined in \sref{cmatch-scalar-mixed}). The implementation also \emph{must not}
+reduce the vectorized match to a scalar using $\Omega$. An implementation
+\emph{may}, however, $\Omega$-reduce the match result $R$ into an
+\emph{separate} value as mentioned in \sref{cmatch-boolean}.
+
+Under the condition that $\forall v\in s(v=\top)$, the system may post-process
+$F$ (as defined in \aref{cmatch}) such that
+
+$$
+ F' = F_0,
+$$
+
+and return $F'$ in place of $F$.
+
+Note also that $F'$ may be fed back into \aref{cmatch} as an input and that the
+results will be consistent and well-defined according to
+\sref{cmatch-scalar-mixed} (and, consequently, this section).
diff --git a/src/current/doc/manual.sty b/src/current/doc/manual.sty
new file mode 100644
index 00000000..b3524f49
--- /dev/null
+++ b/src/current/doc/manual.sty
@@ -0,0 +1,30 @@
+% manual style package
+
+% these margins ensure that the PDF can be easily scrolled vertically without
+% worrying about alternating margins (good for viewing on screen, but not on
+% paper)
+\usepackage[margin=1.25in]{geometry}
+\usepackage{amsmath}
+
+\setcounter{secnumdepth}{3}
+\setcounter{tocdepth}{3}
+
+% no name yet
+\def\lang{the DSL}
+
+\def\sref#1{Section \ref{s:#1}}
+\def\fref#1{Figure \ref{f:#1}}
+\def\aref#1{Algorithm \ref{a:#1}}
+\def\asref#1#2{A\ref{a:#1}(\ref{a:#1:#2})}
+
+\def\set#1{%
+ \ifmmode%
+ \left\{#1\right\}%
+ \else
+ $\left\{#1\right\}$%
+ \fi%
+}
+\def\boolset{\set{\top,\bot}}
+\def\inbool{\in\boolset}
+
+\def\term#1{{\sl #1}}
diff --git a/src/current/doc/manual.tex b/src/current/doc/manual.tex
new file mode 100644
index 00000000..9d1d80ec
--- /dev/null
+++ b/src/current/doc/manual.tex
@@ -0,0 +1,19 @@
+\documentclass[10pt]{book}
+
+%%begin preamble
+ \usepackage{manual}
+
+ \author{Mike Gerwitz\\LoVullo Associates}
+ \date{\today}
+%%end preamble
+
+\begin{document}
+
+\title{Calc DSL: Design Specification and Programmer's Manual}
+\maketitle
+
+\tableofcontents
+
+\include{chapters/class}
+
+\end{document}
diff --git a/src/current/dot.xsl b/src/current/dot.xsl
new file mode 100644
index 00000000..ed0bb39e
--- /dev/null
+++ b/src/current/dot.xsl
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [dot] fatal: this is not an object/executable file:
+ no symbol dependencies found
+
+
+
+
+
+
+ /* dependency graph of
+
+ */
+
+ digraph "
+
+ " {
+
+ graph [rankdir="LR", ranksep="2"];
+
+
+
+
+
+ }
+
+
+
+
+
diff --git a/src/current/dot/attr-color.xsl b/src/current/dot/attr-color.xsl
new file mode 100644
index 00000000..4ef7c01d
--- /dev/null
+++ b/src/current/dot/attr-color.xsl
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+ #204a87
+
+
+
+
+
+
+ #729fcf
+
+
+
+
+
+
+ #4e9a06
+
+
+
+
+
+
+ #c4a000
+
+
+
+
+
+
+ #888a85
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/attr-extern.xsl b/src/current/dot/attr-extern.xsl
new file mode 100644
index 00000000..318da4a6
--- /dev/null
+++ b/src/current/dot/attr-extern.xsl
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+ dashed
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/attr-keep.xsl b/src/current/dot/attr-keep.xsl
new file mode 100644
index 00000000..3a72af49
--- /dev/null
+++ b/src/current/dot/attr-keep.xsl
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+ red
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/attr-shape.xsl b/src/current/dot/attr-shape.xsl
new file mode 100644
index 00000000..f4bc289f
--- /dev/null
+++ b/src/current/dot/attr-shape.xsl
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+ box
+
+
+
+
+
+
+ octagon
+
+
+
+
+
+
+ component
+
+
+
+
+
+
+ note
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/defnode-attr.xsl b/src/current/dot/defnode-attr.xsl
new file mode 100644
index 00000000..778835a0
--- /dev/null
+++ b/src/current/dot/defnode-attr.xsl
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /\n
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+
+
+
+ ="
+
+ "
+
+
+
+
diff --git a/src/current/dot/defnode.xsl b/src/current/dot/defnode.xsl
new file mode 100644
index 00000000..c34c591b
--- /dev/null
+++ b/src/current/dot/defnode.xsl
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+
+ " [
+
+
+
+
+ ,
+
+
+
+ href="
+
+ "
+
+ ];
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/depout.xsl b/src/current/dot/depout.xsl
new file mode 100644
index 00000000..5b3dbdab
--- /dev/null
+++ b/src/current/dot/depout.xsl
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [root=ctr,fontsize=24,style=bold,label="Yield"];
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+
+ " -> "
+
+ "
+
+
+ [
+
+ ]
+
+
+ ;
+
+
+
+
+
+
+
+
+ error: what do I do!?: unexpected
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/pkg-exec.xsl b/src/current/dot/pkg-exec.xsl
new file mode 100644
index 00000000..1c934bfa
--- /dev/null
+++ b/src/current/dot/pkg-exec.xsl
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: cannot locate symbol dependencies for `
+
+ '
+
+
+
+
+
+
+
+
+
diff --git a/src/current/dot/pkg-obj.xsl b/src/current/dot/pkg-obj.xsl
new file mode 100644
index 00000000..d281cffd
--- /dev/null
+++ b/src/current/dot/pkg-obj.xsl
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/calc-display.xsl b/src/current/include/calc-display.xsl
new file mode 100644
index 00000000..4f9f0fac
--- /dev/null
+++ b/src/current/include/calc-display.xsl
@@ -0,0 +1,702 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+ \left(
+
+
+
+
+
+ \right)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ =0
+
+
+
+ \sum \limits_{
+
+ }
+
+
+
+
+ ^{\grave\#
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+
+
+
+
+ \,\cdot\,
+
+
+
+
+
+ \left(
+
+
+
+
+
+
+ \right)
+
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+ \frac{
+
+
+
+ }{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \left\l
+
+
+
+ \right\r
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \left(
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \right)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \left[
+
+
+
+
+ \text{ and }
+
+
+
+
+
+
+
+
+
+
+
+ \right]
+
+
+
+
+
+ \begin{cases}
+
+ \end{cases}
+
+
+
+ \;\;\;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &
+
+
+
+ [
+
+
+
+
+
+
+ \text{if }
+
+
+
+
+
+
+
+
+
+ \text{otherwise}
+
+
+
+
+
+
+ ]
+
+
+
+ ; \\
+
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ =
+ \not=\;
+ \gt
+ \lt
+ \geq
+ \leq
+
+
+
+
+
+
+
+
+
+
+
+ \left[
+
+
+ ,
+
+
+
+
+ \right]^T
+
+
+
+
+ \left[\begin{array}\\
+
+
+
+ \\
+
+
+
+
+ &
+
+
+ {
+
+ }
+
+
+
+ \end{array}\right]
+
+
+
+
+ \#\left(
+
+ \right)
+
+
+
+ \textrm{cons}\left(
+
+ ,
+
+ \right)
+
+
+
+ \left(
+
+ \right)_0
+
+
+
+ \textrm{cdr}\left(
+
+ \right)
+
+
+
diff --git a/src/current/include/depgen.xsl b/src/current/include/depgen.xsl
new file mode 100644
index 00000000..d897c27d
--- /dev/null
+++ b/src/current/include/depgen.xsl
@@ -0,0 +1,526 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [depgen] *determining symbol dependencies...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [depgen] internal error:
+ could not locate dependency symbol `
+
+ ' in local symbol table; needed by
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \textrm{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [depgen] error: unexpected symbol
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [depgen] warning: unknown symbol `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] !!! fatal: internal classification `
+
+ ' cannot pull in external classification `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/display.xsl b/src/current/include/display.xsl
new file mode 100644
index 00000000..7296b560
--- /dev/null
+++ b/src/current/include/display.xsl
@@ -0,0 +1,551 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scalar
+
+
+
+
+
+
+
+
+
+ generator; vector
+
+
+ (
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+
+ "
+ classification
+
+
+
+ scalar
+
+
+
+ vector
+
+
+
+ matrix
+
+
+
+ [dim
+
+ ]
+
+
+
+
+
+ (
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+
+
+ )
+
+
+
+
+
+
+ (!)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _{
+
+ }
+
+
+
+ _{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fparam
+
+
+
+
+
+ class
+
+
+
+ generator
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \textrm{
+
+ }
+
+
+
+
+
+
+
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ _
+
+
+
+
+
+
+
+ {
+
+
+
+
+
+
+
+ }
+
+
+
+ )
+
+
+
+
+ _{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unknown @name reference:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] !!! unknown let-list type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+ =
+
+
+
+
+ \)
+
+
+ (
+
+ )
+
+
+
+
+ let \(
+
+ \) =
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/dslc-base.xsl b/src/current/include/dslc-base.xsl
new file mode 100644
index 00000000..53a31959
--- /dev/null
+++ b/src/current/include/dslc-base.xsl
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/entry-form.xsl b/src/current/include/entry-form.xsl
new file mode 100644
index 00000000..3d6b3c8b
--- /dev/null
+++ b/src/current/include/entry-form.xsl
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ []
+
+
+
+
+
+
+
+
+
+
+
+ matrix
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ selected
+
+
+
+
+
+ selected
+
+
+
+
+ Yes
+ No
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] warning: unknown param type `
+
+ /
+
+ '
+
+
+
+ Unknown type:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+
+
diff --git a/src/current/include/exslt/str.tokenize.template.xsl b/src/current/include/exslt/str.tokenize.template.xsl
new file mode 100644
index 00000000..6da270b3
--- /dev/null
+++ b/src/current/include/exslt/str.tokenize.template.xsl
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/orderizer.xsl b/src/current/include/orderizer.xsl
new file mode 100644
index 00000000..170bd2b9
--- /dev/null
+++ b/src/current/include/orderizer.xsl
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [orderizer] recursively discovering param classes...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [orderizer] checking previous UI siblings:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/domain.xsl b/src/current/include/preproc/domain.xsl
new file mode 100644
index 00000000..6dc436d3
--- /dev/null
+++ b/src/current/include/preproc/domain.xsl
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ warning: union `
+
+ ' has no subdomains; something is probably wrong
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ warning: typedef `
+
+ ' is empty; something is probably wrong
+
+
+
+
+
+
+
+
+
+
+
+
+ error: typedef `
+
+ ' must not contain both @value and non-@value items
+
+
+
+
+
+
+
+
+ error: malformed typedef `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: preproc:mkdomain on non-value item:
+
+
+
+
+
+
+
+
+
+
+
+
+ internal error: unknown domain source:
+
+
+
+
+
+
diff --git a/src/current/include/preproc/eligclass.xsl b/src/current/include/preproc/eligclass.xsl
new file mode 100644
index 00000000..8e78c09a
--- /dev/null
+++ b/src/current/include/preproc/eligclass.xsl
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/eligclass] generating eligibility class
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/eligclass] error: could not load `
+
+ ' object file
+
+
+
+
+
+
+
+
+
+ [preproc/eligclass] internal: empty eligibility
+ class for `
+
+ '; skipping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/expand.xsl b/src/current/include/preproc/expand.xsl
new file mode 100644
index 00000000..57c68564
--- /dev/null
+++ b/src/current/include/preproc/expand.xsl
@@ -0,0 +1,691 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ matrix
+
+
+
+
+
+
+
+
+ vector
+
+
+
+
+
+
+
+ __is
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __is
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/macros.xsl b/src/current/include/preproc/macros.xsl
new file mode 100644
index 00000000..4c4f8e6b
--- /dev/null
+++ b/src/current/include/preproc/macros.xsl
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] error:
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] *REPASS*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Cannot take index of scalar value:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] waiting to expand rate-each
+
+ (immediate template(s) need expansion)...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rate-each must provide either @yields or @generates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Set of individual
+
+ premiums
+
+
+
+
+
+ Zero if not
+
+ , otherwise one
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/package.xsl b/src/current/include/preproc/package.xsl
new file mode 100644
index 00000000..48536af4
--- /dev/null
+++ b/src/current/include/preproc/package.xsl
@@ -0,0 +1,817 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] error: missing random seed `__rseed'
+
+
+
+
+ [preproc] *beginning macro expansion...
+
+
+
+
+
+
+
+
+
+ [preproc] *macro pass complete; expanding...
+
+
+
+
+
+
+
+
+ [preproc] *expansion complete; generating symbol table...
+
+
+
+
+
+
+
+
+
+
+ [preproc] *symbol table generated; checking for
+ unprocessed templates...
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] error:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] error:
+
+
+
+
+ ~~~~[begin document dump]~~~~
+
+ ~~~~[end document dump]~~~~
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] compiling fragments...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] fatal: unexpanded template parameter:
+
+
+
+
+ [preproc] fatal: reference node:
+
+
+
+ ~~~~[begin document dump]~~~~
+
+ ~~~~[end document dump]~~~~
+
+ [preproc] notice: Document dumped.
+
+
+
+
+
+
+ [preproc] fatal: unexpanded template:
+
+
+
+
+ [preproc] fatal: reference node:
+
+
+
+
+
+ ~~~~[begin document dump]~~~~
+
+ ~~~~[end document dump]~~~~
+
+ [preproc] notice: Document dumped.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc]
+
+ template(s) still need application:
+
+
+
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] fatal: unable to locate symbols for
+ remaining templates:
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] fatal: terminating due to errors
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] *expansion complete (recursive)
+
+
+
+
+
+
+
+
+
+
+
+
+ !!! [preproc] fatal: expansion of remaining
+ templates aborted (have all been imported?):
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] template symbol not yet available:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] !!! recursion limit reached in resolving `
+
+ ' symbols
+
+
+
+
+
+
+
+
+ [preproc] *resolving symbol attributes...
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] *SYM REPASS*
+
+ [preproc] The following
+
+ symbol(s) are still unresolved:
+
+
+
+
+ [preproc] -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] !!! failed to look up symbol `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] deferring `
+
+ ' dimensions with unresolved dependencies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] !!! failed to determine dimensions of `
+
+ '
+
+
+
+
+
+ [preproc] resolved `
+
+ ' dimensions as `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !!!
+
+
+
+ (
+
+ )
+
+
+ :
+
+
+
+
+
+
+
+ Compilation failed due to validation errors.
+
+
+
+
+
+
+
+ ~~~~[begin document dump]~~~~
+
+ ~~~~[end document dump]~~~~
+ internal: document dumped.
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/path.xsl b/src/current/include/preproc/path.xsl
new file mode 100644
index 00000000..469603d6
--- /dev/null
+++ b/src/current/include/preproc/path.xsl
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+ ../
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ../
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preproc/symtable.xsl b/src/current/include/preproc/symtable.xsl
new file mode 100644
index 00000000..9210c76c
--- /dev/null
+++ b/src/current/include/preproc/symtable.xsl
@@ -0,0 +1,959 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] discovering symbols...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] warning: symbol /
+
+ /
+
+ has @override set, but does not override anything
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] error: cannot override non-virtual symbol /
+
+ /
+
+
+
+
+
+
+
+ [preproc/symtable] error: duplicate symbol /
+
+ /
+
+ (defined in ./
+
+
+
+
+ and ./
+
+
+
+
+ )
+
+
+
+ ; did you forget @override?
+
+
+
+
+
+
+
+
+ ~~~~[begin document dump]~~~~
+
+ ~~~~[end document dump]~~~~
+
+ ~~~~[begin symbol dump]~~~~
+
+ ~~~~[end symbol dump]~~~~
+
+
+ [preproc/symtable] fatal: aborting due to symbol errors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] done.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ extern mismatch: '
+
+ ' (imported from
+
+ )
+
+
+
+ ;
+
+
+ =
+
+ ,
+
+ expected
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ unresolved extern '
+
+ '
+
+
+
+ (required by
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] processing symbol table...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] error: refusing to import non-package
+
+ ; use @allow-nonpkg to force (if you know what you are doing)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] importing symbol table of
+
+ ...
+
+
+
+
+
+ [preproc/symtable] internal error:
+ failed to locate symbol table:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+ 1
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] internal error:
+ failed to resolve type primitve of `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \textrm{
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc/symtable] internal error:
+ failed to resolve type:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+ 2
+
+
+
+ 0
+
+
+
+
+
diff --git a/src/current/include/preproc/template.xsl b/src/current/include/preproc/template.xsl
new file mode 100644
index 00000000..e1e8edb9
--- /dev/null
+++ b/src/current/include/preproc/template.xsl
@@ -0,0 +1,1149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Undefined template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] expanding template parameters for
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Undefined template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ undefined template param
+ /
+ ; available params are
+
+
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] preparing inline template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] deferring application of unknown template
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] expanding param-copy...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ warning:
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unknown template comparison attribute for
+
+ in
+
+ :
+
+
+
+
+ ="
+
+ "
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: unable to determine @yields for class `
+
+ ' (has the class been imported?)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ error: unknown param node content:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/preprocess.xsl b/src/current/include/preprocess.xsl
new file mode 100644
index 00000000..b0d8cd53
--- /dev/null
+++ b/src/current/include/preprocess.xsl
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [preproc] [rater]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/symbol-map.xml b/src/current/include/symbol-map.xml
new file mode 100644
index 00000000..9cf64218
--- /dev/null
+++ b/src/current/include/symbol-map.xml
@@ -0,0 +1,80 @@
+
+
+
+ \Theta
+
+
+ \theta
+
+
+ C
+
+
+ E
+
+ \kappa
+
+
+ K
+
+
+
+
+
+
+
+ \omega
+
+
+ G
+
+ \sigma
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/include/util.xsl b/src/current/include/util.xsl
new file mode 100644
index 00000000..0e0030fe
--- /dev/null
+++ b/src/current/include/util.xsl
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "
+
+
+
+ ":
+
+
+
+
+ [
+
+
+ ,
+
+
+
+
+ ]
+
+
+
+ {
+
+
+ ,
+
+
+
+
+ }
+
+
+
+ "
+
+
+
+ "
+
+
+
+ [util] !!! invalid util:json
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/link.xsl b/src/current/link.xsl
new file mode 100644
index 00000000..1c984614
--- /dev/null
+++ b/src/current/link.xsl
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/src/current/map.xsd b/src/current/map.xsd
new file mode 100644
index 00000000..d10d3ceb
--- /dev/null
+++ b/src/current/map.xsd
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
+
+ Classification name (lv:classify/@as)
+
+
+
+
+
+
+
+ Classification should not add a match requiring that at least one
+ eligible supplier use it (if supported by implementation)
+
+
+
+
+
+
+
+
+
+ String constant
+
+
+
+
+
+
+
+
+
+
+ Default complex value for a translation
+
+ Concatenates each value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Defines a translation for a given value
+
+
+
+
+
+
+
+
+
+
+
+ Source value to match against for translation
+
+
+
+
+
+
+
+ Value to translate to
+
+
+
+
+
+
+
+ Default value when the resulting translation is the
+ empty string
+
+
+
+
+
+
+
+
+
+ Defines translation rules between source and destination fields; not
+ to be used with @from
+
+
+
+
+
+
+
+
+
+
+
+
+ Identifier of source field
+
+
+
+
+
+
+
+ Optional default value if no source value is available
+
+
+
+
+
+
+
+ Whether this field should be considered when generating eligibility
+ classes (if supported by implementation); default true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Maps a static value
+
+
+
+
+
+
+
+ Static value to map to destination
+
+
+
+
+
+
+
+
+
+
+ Maps a source value to its destination by index
+
+
+
+
+
+
+
+ Source field identifier
+
+
+
+
+
+
+
+ Iterator variable or constant integer representing the source
+ value index
+
+
+
+
+
+
+
+
+
+
+
+
+ Translates source data into a set
+
+
+
+
+
+
+
+
+
+
+ Source field identifier to use as index for the iterator
+
+
+
+
+
+
+
+ Variable to serve as a reference for the iterator index
+
+
+
+
+
+
+
+ When true, if a transformation yields a value that is undefined, an
+ empty string, or the string "0", then omit it from the set
+
+
+
+
+
+
+
+
+
+ Defines a map from a source field to a destination field with optional
+ transformation rules
+
+
+
+
+
+
+
+
+
+
+
+ Identifier of destination field
+
+
+
+
+
+
+
+ Identifier of source field if no data transformations are to be
+ performed; cannot be used with @value
+
+
+
+
+
+
+
+ Constant value to be mapped to destination; cannot be used with @from
+ or from node
+
+
+
+
+
+
+
+ Whether this field should be considered when generating eligibility
+ classes (if supported by implementation); default true
+
+
+
+
+
+
+
+ Override mapping sharing the same destination identifier in an
+ imported package
+
+
+
+
+
+
+
+
+
+ Maps from a source field to a destination field of the same name without
+ any translation; shorthand for identical @to and @from attributes on a
+ general map node
+
+
+
+
+
+
+ Identifier of the source (and consequently destination) field
+
+
+
+
+
+
+
+ Do not validate that the field exists; useful for mapping data that is
+ not explicitly recognized as a field by the source
+
+
+
+
+
+
+
+ Whether this field should be considered when generating eligibility
+ classes (if supported by implementation); default true
+
+
+
+
+
+
+
+ Override mapping sharing the same destination identifier in an
+ imported package
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Includes mappings from another source file
+
+
+
+
+
+
+ Path to source file
+
+
+
+
+
+
+
+
+
+ Maps program data between two points
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Source document to validate against (document root node must be
+ known to the implementation)
+
+
+
+
+
+
+
+
+
+
+ Specifies data transformations/filtering to be performed on data before
+ being returned to a caller
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/pkg-dep.xsl b/src/current/pkg-dep.xsl
new file mode 100644
index 00000000..64c6e9fa
--- /dev/null
+++ b/src/current/pkg-dep.xsl
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/scripts/entry-form.js b/src/current/scripts/entry-form.js
new file mode 100644
index 00000000..b67d9a22
--- /dev/null
+++ b/src/current/scripts/entry-form.js
@@ -0,0 +1,2164 @@
+/**
+ * This file is used for direct interaction with the rater for testing purposes.
+ * As such, much of it is a rushed implementation; it's a bit of a kluge and
+ * could use some refactoring.
+ *
+ * Also, it is terriby stateful and difficult to work with. I have the utmost
+ * confidence in your ability to look away and pretend you never saw this
+ * script.
+ */
+
+// intentionally global; developers can override
+var program = document.location.pathname.match( '/raters/(.*?)/' )[1],
+ submit_url = '/raters/submit-test.php?program=' + program,
+ supplier = rater.supplier,
+ prior_url = '/raters/submit-test.php?retrieve=' + supplier +
+ '&program=' + program,
+ qdata_host = 'dev';
+
+var client = ( function()
+{
+ // URL to which quote/result submissions should be POSTed
+ var form = document.querySelector( 'form.entry-form' ),
+ final_prem = form.querySelector( '.final-premium' ),
+ final_accept = form.querySelector( '.final-accept' ),
+ final_comments = form.querySelector( '.final-comments' ),
+ voi = document.getElementById( 'voi-list' ),
+ coview = document.getElementById( 'class-overview-list' ),
+
+ final_good = document.getElementById( 'final-accept-good' ),
+ final_bad = document.getElementById( 'final-accept-bad' ),
+
+ load_prior = document.getElementById( 'load-prior' ),
+
+ workstatus = null,
+
+ valspan = {},
+ bucket = {},
+ rate_result = {},
+
+ // used to overwrite existing test cases rather than create a new
+ save_id = '',
+ prior_result,
+
+ rate_callback = function() {},
+
+ // whether to ignore user input (do not put in bucket)
+ ignore_input = false;
+
+
+ populateBucket();
+
+
+ function setWorkStatus( message )
+ {
+ if ( workstatus === null )
+ {
+ workstatus = document.createElement( 'div' );
+ workstatus.id = 'workstatus';
+
+ document.body.appendChild( workstatus );
+ }
+
+ workstatus.innerHTML = message;
+ workstatus.className = ( message ) ? 'show' : '';
+ }
+
+ function populateBucket()
+ {
+ Array.prototype.slice.call( form.querySelectorAll( '[name]' ) ).forEach(
+ function( field )
+ {
+ var name = field.name.replace( /\[\]$/, '' );
+
+ if ( !name )
+ {
+ return;
+ }
+
+ // if the name does not match, then we removed the square
+ // brackets, meaning that this is a set
+ bucket[ name ] = ( name === field.name )
+ ? field.value
+ : [ field.value ];
+ }
+ );
+ }
+
+
+ function overrideBucket( boverride )
+ {
+ for ( var name in boverride )
+ {
+ bucket[ name ] = boverride[ name ];
+ }
+
+ emptyBucket();
+ }
+
+
+ function removeEntryFocus()
+ {
+ form.className = form.className.replace( /\bfocus\b/, '' );
+ }
+
+ document.body.addEventListener( 'mouseup', function( e )
+ {
+ var overform = hasParent( form, e.target );
+
+ if ( overform === false )
+ {
+ removeEntryFocus();
+ }
+ } );
+
+ form.addEventListener( 'reset', function()
+ {
+ if ( ignore_input )
+ {
+ return;
+ }
+
+ // wait until *after* reset
+ setTimeout( function()
+ {
+ clearTestCase();
+
+ bucket = {};
+ populateBucket();
+ clearSummaryPremium();
+
+ setWorkStatus();
+ }, 0 );
+ } );
+
+ form.addEventListener( 'mouseover', function()
+ {
+ showEntryForm();
+ } );
+
+
+ function clearTestCase()
+ {
+ save_id = '';
+ prior_result = undefined;
+
+ // clear prior message
+ Prior.setPriorMessage( null );
+
+ // clear prior class from body
+ document.body.className = document.body.className.replace(
+ /\bprior\b/, ''
+ );
+ }
+
+
+ function setTestCase( id, result )
+ {
+ save_id = ''+( id );
+ prior_result = result;
+
+ // this really should be set...
+ if ( !( prior_result.vars ) )
+ {
+ prior_result.vars = {};
+ }
+
+ // add prior class name to body
+ document.body.className += ' prior';
+ }
+
+
+ function showEntryForm()
+ {
+ if ( form.className.match( /\bfocus\b/ ) )
+ {
+ return;
+ }
+
+ form.className += ' focus';
+ }
+
+
+ // on field change, update bucket
+ form.addEventListener( 'change', function( e )
+ {
+ if ( ignore_input )
+ {
+ return;
+ }
+
+ // if we changed something, then the displayed premium (if any) must be
+ // invalidated
+ clearSummaryPremium();
+
+ var target = e.target,
+ name = target.name.replace( /\[\]$/, '' ),
+ value = target.value.trim();
+
+ if ( !name )
+ {
+ return;
+ }
+
+ // if this is a set, we want to store every value
+ if ( name !== target.name )
+ {
+ var toarr = Array.prototype.slice;
+
+ // retrieve all the rows
+ var rows = toarr.call(
+ target.parentElement.parentElement.parentElement
+ .querySelectorAll( '.entry-row' )
+ );
+
+ // determine if we're working with a matrix
+ var matrix = /\bmatrix\b/.test( rows[ 0 ].className );
+
+ value = [];
+ rows.forEach( function( row, i )
+ {
+ var ref = value;
+
+ // for matricies, add value to a sub-array; vectors, just keep
+ // appending to the original array
+ if ( matrix )
+ {
+ ref = value[ i ] = [];
+ }
+
+ // add each value
+ toarr.call( row.querySelectorAll( '[name]' ) ).forEach(
+ function( node )
+ {
+ ref.push( node.value.trim() );
+ }
+ );
+ } );
+ }
+
+ bucket[ name ] = value;
+ } );
+
+ // update screen on submit
+ form.addEventListener( 'submit', function( e )
+ {
+ // do not submit the form
+ e.preventDefault();
+ rate( bucket );
+ } );
+
+ form.addEventListener( 'click', function( e )
+ {
+ if ( e.target.className === 'entry-add' )
+ {
+ addRow( e.target.parentElement, e.target );
+ e.preventDefault();
+ }
+ else if ( e.target.className === 'entry-rm' )
+ {
+ removeColumn( e.target );
+ e.preventDefault();
+ }
+ else if ( e.target.className === 'entry-add-matrix' )
+ {
+ addColumn( e.target );
+ e.preventDefault();
+ }
+ } );
+
+
+
+ final_good.addEventListener( 'click', function( e )
+ {
+ e.preventDefault();
+
+ showFinalComments( true, function( comment, _, waiting )
+ {
+ var prem = rate_result.premium;
+
+ hideFinalAccept();
+ submitQuote( bucket, rate_result, comment, true, waiting, prem, save_id );
+ } );
+ } );
+
+ final_bad.addEventListener( 'click', function( e )
+ {
+ e.preventDefault();
+
+ showFinalComments( false, function( comment, expect, waiting )
+ {
+ hideFinalAccept();
+ submitQuote( bucket, rate_result, comment, false, waiting, expect, save_id );
+ } );
+ } );
+
+
+ function showFinalComments( looksgood, callback )
+ {
+ final_comments.className += ' show';
+
+ var submit = document.getElementById( 'final-submit' ),
+ cancel = document.getElementById( 'final-cancel' ),
+
+ expect_container = document.getElementById(
+ 'final-expect-container'
+ ),
+
+ submit_new = document.getElementById( 'final-submit-new' ),
+
+ listener;
+
+ // we do not care about the expected value if the premium looks good
+ expect_container.style.display = ( looksgood )
+ ? 'none'
+ : 'inline';
+
+ // if a test case is set, give them the option to clear it and submit it
+ // as a new test case
+ submit_new.style.display = ( save_id )
+ ? 'inline'
+ : 'none';
+
+ // make it very clear what the user is about to do
+ submit.innerHTML = ( save_id )
+ ? 'Update Existing Test Case'
+ : 'Submit';
+
+ // we won't use addEventListener becuase we only want one event to be
+ // attached
+ submit.onclick = function( e )
+ {
+ e.preventDefault();
+
+ var comments = document.getElementById( 'final-comments' ),
+ expected = document.getElementById( 'final-expected' ),
+ waiting = document.getElementById( 'final-waiting' );
+
+ callback(
+ comments.value,
+ +( expected.value.replace( /^\$/, '' ) ),
+ !!waiting.checked
+ );
+
+ rmclass( final_comments, 'show' );
+ };
+
+ submit_new.onclick = function( e )
+ {
+ e.preventDefault();
+
+ // clear save id and trigger normal submit
+ save_id = '';
+ submit.onclick( e );
+ };
+
+ cancel.onclick = function( e )
+ {
+ e.preventDefault();
+ rmclass( final_comments, 'show' );
+ };
+
+ // give focus to final comments
+ document.getElementById( 'final-comments' ).focus();
+ }
+
+
+ function hideFinalAccept()
+ {
+ // replace all shows since there may be multiple
+ final_accept.className = final_accept.className.replace(
+ /\bshow\b/,
+ ''
+ );
+ }
+
+
+ function getXhrJsonSync( method, url, data )
+ {
+ var xhttp = new XMLHttpRequest();
+
+ xhttp.open( method, url, false );
+
+ if ( method.toLowerCase() === 'post' )
+ {
+ xhttp.setRequestHeader( 'Content-type',
+ 'application/x-www-form-urlencoded'
+ );
+ }
+
+ xhttp.send( ( data ) ? 'data=' + JSON.stringify( data ) : null );
+
+ if ( xhttp.status !== 200 )
+ {
+ throw Error( 'Submit failed; status: ' + xhttp.status );
+ }
+
+ // this will fail if the response is crap, but will be caught by the
+ // exception
+ return JSON.parse( xhttp.responseText );
+ }
+
+
+ function getXhrJson( method, url, data, callback )
+ {
+ var xhttp = new XMLHttpRequest();
+ xhttp.open( method, url, true );
+
+ if ( method.toLowerCase() === 'post' )
+ {
+ xhttp.setRequestHeader( 'Content-type',
+ 'application/x-www-form-urlencoded'
+ );
+ }
+
+ xhttp.onload = function()
+ {
+ if ( xhttp.status !== 200 )
+ {
+ callback( null,
+ Error( 'Submit failed; status: ' + xhttp.status )
+ );
+ return;
+ }
+
+ callback( JSON.parse( xhttp.responseText ) );
+ }
+
+ xhttp.send( ( data ) ? 'data=' + JSON.stringify( data ) : null );
+ }
+
+
+ function submitQuote(
+ bucket, result, comment, looksgood, waiting, expected, caseid, success_callback
+ )
+ {
+ // we don't want to modify the original result (could use
+ // Object.create() here, but they may be using IE)
+ var tmpresult = function() {};
+ tmpresult.prototype = result;
+
+ // it is absolutely pointless to store debug information since the ids
+ // change at any time and are dependent on the XSL processor
+ var submit_result = new tmpresult();
+
+ // so that it's property serialized
+ for ( var name in result )
+ {
+ submit_result[ name ] = result[ name ];
+ }
+
+ // we do not need the debug information (there's a lot of it and it
+ // changes frequently)
+ submit_result.debug = undefined;
+
+ // nor do we need constants (especially large ones)!
+ submit_result.consts = undefined;
+
+ var data = {
+ bucket: bucket,
+ result: submit_result,
+ looksgood: !!looksgood,
+ waiting: !!waiting,
+ comment: encodeURIComponent( comment ),
+ expected: expected,
+ supplier: supplier,
+
+ // will cause an existing test case to be overwritten, if set
+ caseid: caseid,
+ };
+
+ getXhrJson( 'POST', submit_url, data, function( response, err )
+ {
+ // check the response of the actual save (just because we
+ // got a HTTP 200 doesn't mean we successfully saved to the
+ // server; we could have also hit the wrong page
+ // (misconfigured)!)
+ if ( err )
+ {
+ alert(
+ 'Ah, crap! Quote submission failed! Contact IT before ' +
+ 'you do anything else.\n\n' +
+ 'Here are the boring details:\n' +
+ ' ' + err.message
+ );
+
+ return;
+ }
+
+ success_callback && success_callback();
+ } );
+ }
+
+
+
+ function addRow( parent, before )
+ {
+ before = before || parent.querySelector( '.entry-add' );
+
+ // get the row to duplicate
+ var dup = parent.querySelector( '.entry-row' )
+ .cloneNode( true );
+
+ parent.insertBefore( dup, before );
+
+ // trigger change so that its value can be recorded
+ triggerChange( dup.querySelector( '[name]' ) );
+ }
+
+
+ function addColumn( event_target )
+ {
+ // get the field to duplicate
+ var dup = event_target.parentElement.querySelector( '.entry-field' )
+ .cloneNode( true );
+
+ event_target.parentElement.insertBefore( dup, event_target );
+
+ // trigger change so that its value can be recorded
+ triggerChange( dup.querySelector( '[name]' ) );
+ }
+
+
+ function removeColumn( event_target )
+ {
+ var rm = event_target.parentElement,
+ parent = rm.parentElement,
+ rowParent = parent.parentElement,
+
+ rows = rowParent.querySelectorAll( '.entry-row' ).length,
+ cols = parent.querySelectorAll( '.entry-field' ).length;
+
+ // do not remove last column of last row
+ if ( ( rows + cols ) === 2 )
+ {
+ return;
+ }
+
+ // remove the element
+ parent.removeChild( rm );
+
+ // if there are no more columns, remove the row
+ if ( cols === 1 )
+ {
+ rowParent.removeChild( parent );
+ }
+
+ // re-gather values in bucket to accomodate missing value (we can do so
+ // simply by triggering a change on one of the elements of the same
+ // name)
+ triggerChange( rowParent.querySelector( '[name]' ) );
+ }
+
+
+ function triggerChange( element )
+ {
+ if ( !element )
+ {
+ return;
+ }
+
+ // create change event
+ var event = document.createEvent( 'Event' );
+ event.initEvent( 'change', true, true );
+
+ // trigger event
+ element.dispatchEvent( event );
+ }
+
+
+ function rate( args, showresults, exception )
+ {
+ showresults = ( showresults === undefined ) ? true : !!showresults;
+ exception = !!exception;
+
+ var rater = window.rater;
+
+ if ( !( window.rater ) )
+ {
+ alert( 'fatal: rater unavailable.' );
+ return;
+ }
+
+ setWorkStatus( 'Performing rating...' );
+
+ try
+ {
+ var result = rater( args );
+
+ // XXX: ewwww
+ rate_result = result;
+
+ if ( !( showresults ) )
+ {
+ return;
+ }
+
+ // log result to the console in case we want to peeky peeky
+ console.log( result );
+
+ rate_callback( result );
+
+ setWorkStatus( 'Updating premium...' );
+ updateSummaryPremium( result.premium );
+
+ // VOIs are referenced immediately, so render them first
+ updateVois( result.vars, function()
+ {
+ // classes are faster to process than the other summary values
+ updateSummaryClasses(
+ result.classes,
+ result.vars,
+ undefined,
+
+ function()
+ {
+ updateSummaryValues( result.vars );
+ }
+ );
+ } );
+ }
+ catch ( e )
+ {
+ setWorkStatus( 'Rating error occurred.' );
+
+ console && console.log( e );
+
+ if ( exception )
+ {
+ throw e;
+ }
+ else
+ {
+ alert( 'fatal: ' + e.message );
+ }
+ }
+ }
+
+
+ function updateSummaryPremium( premium )
+ {
+ final_prem.innerHTML = premium;
+ final_prem.className += ' show';
+
+ final_accept.className += ' show';
+
+ setPlaceholderValue( 'yields_premium', '', premium );
+ }
+
+
+ function clearSummaryPremium()
+ {
+ final_prem.innerHTML = '';
+
+ rmclass( final_prem, 'show' );
+ rmclass( final_accept, 'show' );
+ }
+
+
+ function getValueDisplay( value )
+ {
+ if ( Array.isArray( value ) )
+ {
+ return joinValues( value );
+ }
+
+ return ( value === undefined )
+ ? ''
+ : ''+( value );
+ }
+
+
+ function updateVois( vars, callback )
+ {
+ setWorkStatus( 'Processing VOIs...' );
+ voi.innerHTML = '';
+
+ var queue = [];
+ for ( var name in vars )
+ {
+ queue.push( name );
+ }
+
+ var vois = {},
+ qlen = queue.length,
+ i = qlen;
+
+ dequeueSetsOf( 10, function( c )
+ {
+ if ( i-- === 0 )
+ {
+ // display the VOIs
+ processVois( vois );
+ document.getElementById( 'voi-container' ).className += ' show';
+
+ setWorkStatus();
+ callback && callback();
+
+ return;
+ }
+
+ setWorkStatus(
+ 'Processing VOIs (' +
+ Math.floor( ( ( qlen - i ) / qlen ) * 100 ) +
+ '%)...'
+ );
+
+ var name = queue[ i ],
+ value = vars[ name ];
+
+ if ( value
+ && /^prem|^min|^surcharge|^cov(erage)?|^credit|^factor|^rate|Prem|[tT]otal/
+ .test( name )
+ && !( /^_/.test( name ) )
+ )
+ {
+ var display = getValueDisplay( value ),
+ prior = ( prior_result && prior_result.vars[ name ] )
+ ? getValueDisplay( prior_result.vars[ name ] )
+ : '';
+
+ // update values of interest (voi)
+ if ( display !== '[]' )
+ {
+ vois[ name ] = [ display, prior ];
+ }
+ }
+
+ // continue
+ c();
+ } )();
+ }
+
+
+ function updateSummaryValues( vars, placeid, callback )
+ {
+ var queue = [];
+
+ for ( var name in vars )
+ {
+ queue.push( name );
+ }
+
+ var qlen = queue.length;
+
+ // repaint frequently; this is intensive
+ dequeueSetsOf( 10, function( c )
+ {
+ if ( queue.length === 0 )
+ {
+ setWorkStatus();
+ return;
+ }
+
+ name = queue.pop();
+
+ setWorkStatus(
+ 'Formatting summary values (' +
+ Math.floor( ( ( qlen - queue.length ) / qlen ) * 100 ) +
+ '%)...'
+ );
+
+ var value = vars[ name ],
+ display = getValueDisplay( value ),
+ prior = ( prior_result && prior_result.vars[ name ] )
+ ? getValueDisplay( prior_result.vars[ name ] )
+ : '';
+
+
+ setPlaceholderValue( name, '', display );
+
+ if ( prior )
+ {
+ setPlaceholderValue( name, '-prior', prior );
+ }
+
+ setLetListPlaceholders( name, display, prior );
+
+ // continue
+ c();
+ } )();
+ }
+
+
+ function dequeueSetsOf( n, c )
+ {
+ return function dq( i )
+ {
+ i = i || 0;
+
+ c( function()
+ {
+ if ( i === 0 )
+ {
+ setTimeout( function()
+ {
+ dq( n )
+ }, 0 );
+ }
+ else
+ {
+ dq( i - 1 );
+ }
+ } );
+ }
+ }
+
+
+ function processVois( vois )
+ {
+ // add the vois to the screen in the proper order (reversed)
+ var i = window.voi_order.length;
+ while ( i-- )
+ {
+ var data = window.voi_order[ i ],
+ name = data[ 0 ],
+ depth = data[ 1 ],
+ href = data[ 2 ];
+
+ if ( vois[ name ] )
+ {
+ var voi = vois[ name ];
+ addVoi( name, voi[ 0 ], voi[ 1 ], href, depth );
+ }
+ }
+ }
+
+
+ function addVoi( name, value, prior, href, depth )
+ {
+ depth = depth || 0;
+
+ // if the VOI has a value other than 0 (our poor-man check is using a
+ // regex to remove anything and see if we have a non-empty string left)
+ if ( ( value.replace( /[\[\]0,]/g, '' ) === '' )
+ && ( prior.replace( /[\[\]0,]/g, '' ) === '' )
+ )
+ {
+ return;
+ }
+
+ var depthstr = '',
+ i = depth;
+ while ( i-- )
+ {
+ if ( i === 0 )
+ {
+ depthstr += '|-';
+ }
+
+ depthstr += ' ';
+ }
+
+ // if href is not given, then use name
+ href = href || name;
+
+ // got lazy.
+ var tr = document.createElement( 'tr' );
+ tr.className = 'depth' + depth;
+ tr.innerHTML = (
+ '
' +
+ '' +
+ depthstr + name +
+ ' ' +
+ ' ' +
+ '' + depthstr.replace( /-/, '' ) + value + ' ' +
+ ( ( !prior ) ? '' :
+ '' + prior + ' '
+ )
+ );
+
+ tr.addEventListener( 'click', function( e )
+ {
+ // ignore link clicks
+ if ( e.target.nodeName === 'A' )
+ {
+ return;
+ }
+
+ var val = JSON.parse( value );
+ if ( Array.isArray( val ) )
+ {
+ var t = 0;
+ for ( var i in val )
+ {
+ t += val[ i ];
+ }
+
+ val = t;
+ }
+
+ voiPainterAdd( tr, val );
+ } );
+
+ voi.appendChild( tr );
+ }
+
+
+ function addClassOverview( name, value )
+ {
+ var prior = ( prior_result && prior_result.vars[ name ] )
+ ? getValueDisplay( prior_result.vars[ name ] )
+ : '';
+
+ // got lazy.
+ var tr = document.createElement( 'tr' );
+ tr.innerHTML = (
+ '' +
+ '' +
+ name +
+ ' ' +
+ ' '
+ );
+
+ coview.appendChild( tr );
+ }
+
+
+ function joinValues( values )
+ {
+ var ret = '[';
+
+ if ( Array.isArray( values[ 0 ] ) )
+ {
+ var subvals = [];
+
+ for ( var i in values )
+ {
+ subvals.push( joinValues( values[ i ] ) );
+ }
+
+ ret += subvals.join( ', ' );
+ }
+ else
+ {
+ ret += ( Array.isArray( values ) )
+ ? values.join( ', ' )
+ : values;
+ }
+
+ return ret + ']';
+ }
+
+
+ function updateSummaryClasses( classes, vars, placeid, callback )
+ {
+ coview.innerHTML = '';
+
+ var queue = [];
+
+ for ( var name in classes )
+ {
+ queue.push( name );
+ }
+
+ var qlen = queue.length;
+
+ dequeueSetsOf( 10, function( c )
+ {
+ if ( queue.length === 0 )
+ {
+ setWorkStatus();
+ callback && callback();
+
+ return;
+ }
+
+ var name = queue.pop();
+
+ setWorkStatus(
+ 'Formatting class summary values (' +
+ Math.floor( ( ( qlen - queue.length ) / qlen ) * 100 ) +
+ '%)...'
+ );
+
+ // output the classification and the total premium for the class
+ setPlaceholderValue( 'class-' + name, placeid,
+ (
+ ''+( classes[ name ] ) +
+ ' -> ' +
+ vars[ name ]
+ ),
+ classes[ name ]
+ );
+
+ if ( prior_result
+ && prior_result.classes
+ && prior_result.classes[ name ]
+ )
+ {
+ // XXX: duplicate
+ setPlaceholderValue( 'class-' + name, '-prior',
+ (
+ ''+( prior_result.classes[ name ] ) +
+ ' -> ' +
+ prior_result.vars[ name ]
+ ),
+ classes[ name ]
+ );
+ }
+
+ // if this class was a match, add it to the overview with its
+ // accumulator value
+ if ( classes[ name ] )
+ {
+ addClassOverview( name, vars[ name ] );
+ }
+
+ c();
+ } )();
+
+ document.getElementById( 'class-overview' ).className += ' show';
+ }
+
+
+ function updateSummaryDebug( debug, parent, callback )
+ {
+ var queue = [];
+
+ // do nothing if debug data is not yet available
+ if ( !debug )
+ {
+ return;
+ }
+
+ // loop through each element on the DOM, *not* each debug id returned to
+ // us, since we want to clear any that may be missing
+ Array.prototype.slice.call( parent.querySelectorAll( '.debugid' ) )
+ .forEach( function( element )
+ {
+ queue.push( element.id );
+ } );
+
+ var qlen = queue.length;
+
+ dequeueSetsOf( 10, function( c )
+ {
+ if ( queue.length === 0 )
+ {
+ setWorkStatus();
+ callback && callback();
+
+ return;
+ }
+
+ setWorkStatus(
+ 'Processing breakdown values (' +
+ Math.floor( ( ( qlen - queue.length ) / qlen ) * 100 ) +
+ '%)...'
+ );
+
+ var id = queue.pop(),
+ did = id.replace( /^ubd-/, '' );
+
+ try
+ {
+ setPlaceholderValue( id, '', ( debug[ did ] )
+ ? JSON.stringify( debug[ did ] )
+ : ''
+ );
+ }
+ catch ( e )
+ {
+ console.error(
+ 'Debug (stringify debug ' + did + ' ): ' +
+ e.message
+ );
+ }
+
+ c();
+ } )();
+ }
+
+
+ var getPlaceholder = ( function()
+ {
+ var domcache = {};
+
+ function getPlaceholder( name, placeid )
+ {
+ var classname = ( 'entry-value' + ( placeid || '' ) );
+
+ var current = domcache[ name + placeid ];
+ if ( current )
+ {
+ return current;
+ }
+
+ // ignore system vars
+ if ( name.match( /^___/ ) )
+ {
+ return null;
+ }
+
+ var parent = document.getElementById( name );
+
+ if ( !parent )
+ {
+ return null;
+ }
+
+ var legend = parent.getElementsByTagName( 'legend' ),
+ dest = ( legend.length ) ? legend[ 0 ] : parent;
+
+ var element = document.createElement( 'span' );
+ element.className = classname;
+ dest.appendChild( element );
+
+ // rather than re-scanning the DOM each time
+ domcache[ name + placeid ] = element;
+
+ return element;
+ }
+
+ return getPlaceholder;
+ } )();
+
+
+ function setPlaceholderValue( name, placeid, value, hasval )
+ {
+ var p = getPlaceholder( name, placeid );
+ if ( p === null )
+ {
+ return;
+ }
+
+ p.innerHTML = value;
+
+ // do not handle prior flagging
+ if ( placeid === '-prior' )
+ {
+ return;
+ }
+
+ // get fieldset
+ var fs = p.parentNode.parentNode;
+ if ( fs.nodeName === 'FIELDSET' )
+ {
+ fs.className = fs.className.replace( /\Bhasval\B/, '' );
+ if ( ( hasval !== undefined && hasval )
+ // progressively more time-consuming checks
+ || ( ( hasval === undefined )
+ && value
+ && +value !== 0
+ && value.replace( /[\[\],0]/g, '' )
+ )
+ )
+ {
+ fs.className += ' hasval';
+ }
+ }
+ }
+
+
+ function setLetListPlaceholders( name, value, prior )
+ {
+ if ( name.match( /^___/ ) )
+ {
+ return;
+ }
+
+ // certainly room for improvement here (especially performance-wise),
+ // but this is a quick implementation
+ var elements = document.querySelectorAll( '.letlist-' + name );
+ Array.prototype.slice.call( elements ).forEach( function( element )
+ {
+ if ( !( element.id ) )
+ {
+ // prefix with alpha so as not to cause a syntax error on query
+ element.id = 'll' + Math.floor(
+ ( new Date() ).getTime() * Math.random()
+ );
+ }
+
+ setPlaceholderValue( element.id, '', value );
+
+ // include prior values, if available
+ if ( prior )
+ {
+ setPlaceholderValue( element.id, '-prior', prior );
+ }
+ } );
+ }
+
+
+ function rmclass( element, name )
+ {
+ element.className = element.className.replace(
+ new RegExp( '\\b' + name + '\\b', 'g' ),
+ ''
+ );
+ }
+
+
+ function hasParent( parent, element )
+ {
+ var parentElement = element.parentElement;
+
+ if ( parentElement === parent )
+ {
+ return true;
+ }
+
+ return ( parentElement )
+ ? hasParent( parent, parentElement )
+ : false;
+ }
+
+
+ // XXX: This is a mess. THIS IS WHAT TIME CONSTRAINTS DO TO CODE QUALITY!
+ // LET ME HACK IN PEACE! >:@ (What? Unconstrained development is a fantasy?
+ // Is unlimited time unreasonable? Phf. Maybe that Time Weaver frog person
+ // knows how to help with that. If you don't know that reference and you're
+ // in here hacking this code, then that implies that you are new; it then
+ // begs the question: why has it persisted for so long!!! Of course it has,
+ // though. That's how TODOs/XXXs work: they don't get fixed; they just turn
+ // text in your editor pretty [obnoxious] colors.)
+ function resetFields()
+ {
+ // XXX: gahhhhhh!!!!!!!
+ ignore_input = true;
+
+ function rowquery( name )
+ {
+ return document.querySelectorAll(
+ '#param-input-' + name + ' > .entry-row'
+ );
+ }
+
+ for ( var field in bucket )
+ {
+ // may happen if we're loading data from another source
+ if ( bucket[ field ] === undefined )
+ {
+ continue;
+ }
+
+ var fdata = bucket[ field ],
+ elements = rowquery( field ),
+
+ length = ( fdata.length > elements.length )
+ ? fdata.length
+ : elements.length;
+
+ if ( elements.length === 0 )
+ {
+ continue;
+ }
+
+ // not everything is an array of values
+ if ( Array.isArray( fdata ) )
+ {
+ // add/clear fields on the form as necessary to accomdate bucket
+ // data
+ for ( var i = 0; i < length; i++ )
+ {
+ // field exists in bucket but not on the form
+ if ( ( fdata[ i ] !== undefined ) && !( elements[ i ] ) )
+ {
+ addRow( elements[ 0 ].parentNode );
+ }
+ // field exists on form but not in the bucket
+ else if ( elements[ i ] && ( fdata[ i ] === undefined ) )
+ {
+ // TODO: remove field instead
+ elements[ i ].querySelector( '[name]' ).value = '';
+ }
+
+ // if we have a matrix of values, we must also add columns
+ // for each
+ if ( Array.isArray( fdata[ i ] ) )
+ {
+ var element = rowquery( field )[ i ],
+ cols = element.querySelectorAll(
+ '.entry-field'
+ ),
+
+ len = ( fdata[ i ].length > cols.length )
+ ? fdata[ i ].length
+ : cols.length;
+
+ // check each column
+ for ( var j = 0; j < len; j++ )
+ {
+ if ( ( fdata[ i ][ j ] !== undefined )
+ && !( cols[ j ] )
+ )
+ {
+ // re-query in case we just added a row
+ addColumn( element.querySelector(
+ '.entry-add-matrix'
+ ) );
+ }
+ else if ( cols[ j ]
+ && ( fdata[ i ][ j ] === undefined )
+ )
+ {
+ // TODO: remove field instead
+ cols[ i ].querySelector( '[name]' ).value = '';
+ }
+ }
+ }
+ }
+ }
+ }
+
+ form.reset();
+ ignore_input = false;
+ }
+
+
+ function emptyBucket()
+ {
+ resetFields();
+
+ // prevent form updates from propagating to the bucket
+ ignore_input = true;
+
+ for ( var field in bucket )
+ {
+ var fdata = bucket[ field ];
+
+ // not everything is an array; if not, simply set the value and move
+ // on
+ if ( !( Array.isArray( fdata ) ) )
+ {
+ var element = document.querySelector(
+ '[name="' + field + '"]'
+ );
+
+ if ( element )
+ {
+ element.value = fdata;
+ }
+
+ continue;
+ }
+
+ var elements = document.querySelectorAll(
+ '[name="' + field + '[]"]'
+ );
+
+ var total = 0;
+ for ( var i = 0, l = fdata.length; i < l; i++ )
+ {
+ if ( !( elements[ i ] ) )
+ {
+ continue;
+ }
+
+ // if a matrix, update each value
+ if ( Array.isArray( fdata[ i ] ) )
+ {
+ for ( var j = 0, jl = fdata[ i ].length; j < jl; j++ )
+ {
+ elements[ total++ ].value = fdata[ i ][ j ];
+ }
+ }
+ else
+ {
+ // not a matrix
+ elements[ total++ ].value = fdata[ i ];
+ }
+ }
+ }
+
+ // re-allow input
+ ignore_input = false;
+ }
+
+
+ function getUserFromHostname( hostname )
+ {
+ // strip off any domain, remove number from username and strip anything
+ // after a dash (e.g. gerwitm-ubuntu2.lovullo.local => gerwitm)
+ return hostname.split( '.' )[ 0 ].replace( /[0-9]+$/, '' )
+ .split( '-' )[ 0 ];
+ }
+
+
+ /**
+ * Prior module: load prior quotes (test cases)
+ *
+ * Not to be confused in speech with the Friar module, which would have your
+ * premiums divinely calculated and communicated through a deep meditation.
+ */
+ var Prior = ( function ___loadprior( dom )
+ {
+ var exports = {},
+
+ // current set of loaded test cases
+ curset = {};
+
+ var getLoadDialog = function()
+ {
+ // URL with fragment to automatically display this dialog
+ var url = document.location.href.replace( /#.*$/, '' ) + '#prior';
+
+ var dialog = dom.createElement( 'div' );
+ dialog.id = 'prior';
+ dialog.className = 'load-dialog';
+ dialog.innerHTML =
+ "Load Prior Quotes " +
+ "" +
+ "Below is a list of all prior saved quotes; choose one " +
+ "to load it into the test area." +
+ "
" +
+ "" +
+ "To load this dialog automatically on page load, you " +
+ "may use the following link: " +
+ url + " "
+ "
";
+
+ // re-test button
+ var retest = dom.createElement( 'button' );
+ retest.innerHTML = 'Regression Test';
+ retest.addEventListener( 'click', function( e )
+ {
+ e.preventDefault();
+ e.target.disabled = 'disabled';
+
+ retestAll( function()
+ {
+ e.target.disabled = '';
+ } );
+ } );
+
+ // load quote number
+ var loadquote = dom.createElement( 'button' );
+ loadquote.innerHTML = 'Load Quote #';
+ loadquote.addEventListener( 'click', function( e )
+ {
+ e.preventDefault();
+
+ var qid = prompt( 'Enter quote #:' );
+
+ if ( !qid )
+ {
+ return;
+ }
+
+ exports.hideLoad();
+
+ loadQuote( qid, qdata_host );
+ } );
+
+ dialog.appendChild( retest );
+ dialog.appendChild( loadquote );
+ dialog.appendChild( getPriorTable() );
+
+ dom.body.appendChild( dialog );
+
+ // reassign the function to always return the instance
+ getLoadDialog = function()
+ {
+ return dialog;
+ };
+
+ return getLoadDialog();
+ };
+
+
+ var getPriorTable = function()
+ {
+ var table = dom.createElement( 'table' ),
+ headings = [
+ "Date", "Description", "User", "Premium", "Expected"
+ ];
+
+ // add headings
+ for ( var head in headings )
+ {
+ var th = dom.createElement( 'th' );
+ th.innerHTML = headings[ head ];
+ th.className = headings[ head ].toLowerCase();
+
+ table.appendChild( th );
+ }
+
+ // add count
+ var count = dom.createElement( 'caption' );
+ count.innerHTML =
+ 'Total Count: 0 ';
+ table.appendChild( count );
+
+ table.clear = function()
+ {
+ var rows = table.querySelectorAll( 'tr' );
+ for ( var i = 0; i < rows.length; i++ )
+ {
+ table.removeChild( rows[ i ] );
+ }
+ };
+
+ table.addRow = function( looksgood, waiting /*, ... */ )
+ {
+ var tr = dom.createElement( 'tr' );
+
+ // the first argument is the id
+ var id = arguments[ 0 ];
+ tr.id = '_testcase_' + id;
+
+ // the second argument will determine the row color (looksgood)
+ tr.className =
+ ( ( arguments[ 1 ] )
+ ? 'good'
+ : 'bad'
+ ) +
+ ( ( arguments[ 2 ] )
+ ? ' waiting'
+ : ''
+ );
+
+ // all other arguments will be cells
+ for ( var i = 3; i < arguments.length; i++ )
+ {
+ var td = dom.createElement( 'td' );
+ td.innerHTML = arguments[ i ];
+ td.className = headings[ i - 3 ].toLowerCase();
+
+ // first cell will contain a hyperlink for auto-loading on
+ // visit
+ if ( i === 3 )
+ {
+ var a = dom.createElement( 'a' );
+ a.href = ( '#prior/' + id );
+ a.innerHTML = td.innerHTML;
+
+ td.innerHTML = '';
+ td.appendChild( a );
+
+ a.addEventListener( 'click', function( e )
+ {
+ doLoad( id );
+ } );
+ }
+
+ tr.appendChild( td );
+ }
+
+ table.appendChild( tr );
+ };
+
+ table.setCount = function( count )
+ {
+ table.querySelector( '.count' ).innerHTML = +count;
+ };
+
+ table.mark = function( id, type )
+ {
+ table.querySelector( '#_testcase_' + id ).className = type;
+ };
+
+ table.changePremium = function( id, premium )
+ {
+ var element = table.querySelector(
+ '#_testcase_' + id + ' .premium'
+ );
+
+ // add the value and retain the previous value
+ element.innerHTML = '$' + premium +
+ '(was ' + element.innerHTML +
+ ')
';
+ };
+
+ table.changeComment = function( id, comment )
+ {
+ var element = table.querySelector(
+ '#_testcase_' + id + ' .description'
+ );
+
+ element.innerHTML = comment.replace( /\n/g, ' ' );
+ };
+
+ function doLoad( id )
+ {
+ exports.hideLoad();
+
+ // give them an indication that something is happening
+ setTimeout( function()
+ {
+ loadPriorTestCase( id );
+ }, 0 );
+ }
+
+ // when a row is clicked, trigger the load
+ table.addEventListener( 'click', function( e )
+ {
+ // we care only of row clicks
+ if ( e.target.nodeName.toLowerCase() !== 'td' )
+ {
+ return;
+ }
+
+ // get the unique id for this test case
+ var id = e.target.parentNode.id.replace( /^_testcase_/, '' );
+ doLoad( id );
+ } );
+
+ getPriorTable = function()
+ {
+ return table;
+ };
+
+ return getPriorTable();
+ };
+
+
+ function loadPrior()
+ {
+ // first, clear out any existing results
+ getPriorTable().clear();
+
+ // load prior data from server
+ var response = getXhrJsonSync( 'GET', prior_url ),
+ table = getPriorTable(),
+ results = response.results;
+
+ // store the current set of test cases
+ curset = results;
+
+ // add test test case to the table
+ for ( testcase in results )
+ {
+ var result = results[ testcase ];
+
+ table.addRow(
+ result.id,
+ result.looksgood,
+ result.waiting,
+ result.date,
+
+ // comment
+ ( result.comment.replace( /\n/g, ' ' )
+ || '(no comment) '
+ ),
+
+ // username (from hostname)
+ getUserFromHostname( result.hostname ),
+
+ // premium
+ ( '$' + ( result.premium || 0.00 ) ),
+
+ // expected premium
+ ( ( result.expected )
+ ? '$' + result.expected
+ : ( result.looksgood )
+ ? '$' + result.premium
+ : '-'
+ )
+ );
+ }
+
+ table.setCount( results.length );
+ }
+
+
+ function getTestCaseData( id )
+ {
+ return getXhrJsonSync( 'GET', prior_url + '&id=' + id );
+ }
+
+
+ function getQuoteData( id, qdata_host )
+ {
+ try
+ {
+ return getXhrJsonSync(
+ 'GET', prior_url + '&host=' + qdata_host + '&qid=' + id
+ );
+ }
+ catch ( e )
+ {
+ return { error: 'Invalid response from server.' };
+ }
+ }
+
+
+ function showRatingResultPage()
+ {
+ dom.location.hash = 'test-data';
+ }
+
+
+ function loadQuote( qid, host, bucket_override )
+ {
+ var data = getQuoteData( qid, host );
+ if ( data.error !== 'OK' )
+ {
+ alert( data.error );
+ return;
+ }
+
+ rater.fromMap( data.results.bucket, function( data )
+ {
+ bucket = data;
+ emptyBucket();
+
+ if ( bucket_override )
+ {
+ overrideBucket( bucket_override );
+ }
+
+ showRatingResultPage();
+ rate( bucket );
+ } );
+ }
+
+
+ function loadPriorTestCase( id )
+ {
+ var casedata = getTestCaseData( id );
+
+ if ( casedata.status !== 200 )
+ {
+ alert( 'Could not load test case.\n\n' + casedata.error );
+ }
+
+ var data = casedata.results;
+
+ // display the message so that they know what they're looking at
+ exports.setPriorMessage(
+ data.hostname, data.comment, data.looksgood, id
+ );
+
+ // overwrite the bucket
+ bucket = data.bucket;
+ emptyBucket();
+
+ // set this test case so that our next save overwrites it
+ setTestCase( id, data.result );
+
+ // make it obvious to the user that the data has been loaded
+ clearSummaryPremium();
+ showEntryForm();
+
+ // prefill the comment and expected data on the submission form,
+ // leaving room at the top for additional comments
+ document.getElementById( 'final-comments' )
+ .innerHTML = (
+ "\n\n\n" +
+ getPrevSubmitCommentText(
+ data.hostname,
+ data.comment
+ )
+ );
+ document.getElementById( 'final-expected' ).value = data.expected;
+
+ // let the browser catch up and then perform rating
+ setTimeout( function()
+ {
+ // switch to test data and rate
+ document.location.hash = '#test-data';
+ rate( bucket );
+ }, 0 );
+ }
+
+
+ function getPrevSubmitCommentText( hostname, comment )
+ {
+ return "Previously submitted by " +
+ getUserFromHostname( hostname ) + ": " + comment;
+ }
+
+
+ function retestAll( callback )
+ {
+ var queue = [],
+ skipped = 0,
+
+ // regression test results, which may or may not be submitted to
+ // the server
+ history = {};
+
+ // queue each of the test cases
+ for ( var testcase in curset )
+ {
+ queue.push( curset[ testcase ] );
+ }
+
+ var count = failures = changed = 0,
+ start = ( new Date() ).getTime();
+
+ var run = function()
+ {
+ // do not pop(); we want to do them in order so it doesn't look
+ // too odd to the user
+ var test = queue.shift();
+
+ // all done
+ if ( !( test ) )
+ {
+ var time = ( new Date() ).getTime() - start;
+
+ var msg = (
+ 'Test complete. Re-ran ' + count + ' test(s) with ' +
+ failures + ' failure(s) in ' + ( time / 1000 ) + 's.' +
+ "\n\n" +
+
+ ( ( skipped )
+ ? skipped + " test(s) premium checks " +
+ "were skipped because they " +
+ "have no expected premium; please aid in the " +
+ "automated testing of these by selecting " +
+ "them and entering an expected premium when " +
+ "re-submitting it (by clicking Incorrect). " +
+ "These skipped tests are still noted if " +
+ "their premiums changed (in italics), but " +
+ "their success statuses are left untouched."
+ : ''
+ ) +
+
+ ( ( failures === 0 )
+ ? ( !skipped )
+ ? "\n\nYou should feel pretty sweet right now."
+ : ''
+ : "\n\nSomeone's got some splainin' to do."
+ ) +
+
+ ( ( !changed ) ? "\n\nNo test cases have changed." :
+ "\n\n" + changed + " case(s) changed." +
+ "\n\nWould you like the results of this regression " +
+ "to be recorded? This will cause the status of each " +
+ "test case to be updated as shown. If unsure, click " +
+ "'Cancel'."
+ )
+ );
+
+ // if we have changes, show a box asking if the changes
+ // should be uploaded to the server; otheriwse, just alert
+ // (which will return undefined and cast to false)
+ var submit = !!( changed && confirm || alert )
+ .call( window, msg );
+
+ if ( submit )
+ {
+ saveRegression( history );
+ }
+
+ callback && callback( count, failures, time );
+
+ return;
+ }
+
+ var table = getPriorTable();
+ table.mark( test.id, 'testing' );
+
+ setTimeout( function()
+ {
+ var testdata = getTestCaseData( test.id ).results;
+
+ try
+ {
+ // rate, but do not update the screen
+ rate( testdata.bucket, false, true );
+ }
+ catch ( e )
+ {
+ console.log( e );
+ table.mark( test.id, 'skip' );
+
+ // abort! abort!
+ //alert( 'An error occurred. Aborting.' );
+ run();
+ return;
+ }
+
+ // determine what premium we're expecting (default to
+ // existing premium)
+ var expected = testdata.expected || testdata.result.premium,
+ skipme = !( testdata.looksgood || testdata.expected );
+
+ var correct = (
+ rate_result.premium
+ && ( rate_result.premium == expected )
+ );
+
+ // add to changed count if the status changed
+ var has_changed = ( testdata.looksgood !== correct );
+ changed += ( +has_changed && !skipme );
+
+ skipped += +skipme;
+
+ // only add to the total count if the premium was actually
+ // compared
+ if ( !skipme )
+ {
+ count++;
+
+ if ( !( correct ) )
+ {
+ failures++;
+ }
+
+ // store in case the user decides to save to the server
+ if ( has_changed )
+ {
+ history[ test.id ] = {
+ looksgood: correct,
+ bucket: testdata.bucket,
+ result: rate_result,
+ expected: expected,
+ comment: testdata.comment,
+ hostname: testdata.hostname,
+ previous: testdata.result,
+ };
+
+ // show the comment that would be saved to the
+ // server, should they choose to do so
+ table.changeComment(
+ test.id,
+ genRegressionComment( history[ test.id ] )
+ );
+ }
+ }
+
+ // update table
+ table.changePremium( test.id, rate_result.premium );
+ table.mark(
+ test.id,
+ (
+ ( ( correct )
+ ? 'good'
+ : 'bad'
+ ) +
+ ( ( has_changed )
+ ? ' changed'
+ : ''
+ ) +
+ ( ( rate_result.premium !== testdata.result.premium )
+ ? ' premchanged'
+ : ''
+ ) +
+ ( ( skipme )
+ ? ' skipped'
+ : ''
+ )
+ )
+ );
+
+ // continue
+ run();
+ }, 0 );
+ }
+
+ // run 'em one by one
+ setTimeout( run, 0 );
+ }
+
+
+ function genRegressionComment( item )
+ {
+ return "[Regression Test: " +
+ ( ( item.looksgood ) ? "Pass" : "Fail" ) +
+ "] Expected $" + item.expected + "; calculated $" +
+ item.result.premium + "; previously $" +
+ item.previous.premium + "\n\n" +
+ getPrevSubmitCommentText( item.hostname, item.comment );
+ }
+
+
+ function saveRegression( history )
+ {
+ for ( var id in history )
+ {
+ var item = history[ id ];
+
+ // generate comment
+ var comment = genRegressionComment( item );
+
+ submitQuote(
+ item.bucket,
+ item.result,
+ comment,
+ item.looksgood,
+ ( item.waiting || false ),
+ item.expected,
+ id,
+ function() {}
+ );
+ }
+ }
+
+
+ exports.initHtml = function()
+ {
+ getLoadDialog();
+ }
+
+
+ exports.showLoad = function()
+ {
+ removeEntryFocus();
+
+ getLoadDialog().className += ' show';
+ loadPrior();
+ }
+
+
+ exports.hideLoad = function()
+ {
+ var dialog = getLoadDialog();
+ dialog.className = dialog.className.replace( /\bshow\b/g, '' );
+ }
+
+
+ exports.setPriorMessage = function( host, message, good, id )
+ {
+ var container = document.getElementById( 'prior-message' );
+
+ if ( !container )
+ {
+ return;
+ }
+
+ container.style.display = ( message ) ? 'inline-block' : 'none';
+ container.className = ( good ) ? 'good' : 'bad';
+ container.innerHTML = (
+ '' + getUserFromHostname( host ) + ': ' +
+ message
+ .replace( /^\n+|\n+$/g, '' )
+ .replace( / /g, ' ' )
+ .replace( /\t/g, ' ' )
+ .replace( /\n/g, ' ' )
+ .replace(
+ /(Previously submitted by [^:]+:)/g,
+ '$1 '
+ )
+ + '[Direct Link] '
+ );
+ };
+
+ exports.loadQuote = loadQuote;
+ exports.loadPriorTestCase = loadPriorTestCase;
+
+ return exports;
+ } )( document );
+
+
+ function begin()
+ {
+ // initialize prior div
+ Prior.initHtml();
+
+ // allow linking to test cases
+ var pmatch;
+ if ( pmatch = document.location.href.match( /#prior(?:\/(.*))?$/ ) )
+ {
+ var id = pmatch[ 1 ];
+
+ if ( !( id ) )
+ {
+ // no id given; let them choose
+ Prior.showLoad();
+ }
+ else
+ {
+ // we were given an id; load it!
+ console.log( 'Loading ' + id + '...' );
+ Prior.loadPriorTestCase( id );
+ }
+ }
+
+ // allow settings params from the URL (very basic parsing; barely used); we
+ // use a colon rather than ? because ? is not included in the location
+ // object
+ var pdata;
+ var bucket_override = [];
+ if ( pdata = document.location.hash.match( /:(.*)$/ ) )
+ {
+ try
+ {
+ // params delimited by &
+ var params = pdata[1].split( '&' );
+ for ( var param in params )
+ {
+ // values delimited from the name by =
+ var valdata = params[ param ].split( '=' ),
+ val = JSON.parse( valdata[ 1 ] );
+
+ bucket_override[ valdata[ 0 ] ] = val;
+ bucket[ valdata[ 0 ] ] = val;
+
+ console.log( 'Bucket override: ' + valdata[ 0 ] + '=' + val );
+ }
+
+ overrideBucket( bucket_override );
+ }
+ catch ( e )
+ {
+ alert( 'Failed setting param values from URL.\n\n' + e.message );
+ }
+ }
+
+ // allow loading of quote ids
+ var mdata;
+ if ( mdata = document.location.hash.match( /#load\/([a-z]+)\/([0-9]+)/ ) )
+ {
+ var host = mdata[1],
+ id = mdata[2];
+
+ // load the quote
+ Prior.loadQuote( id, host, bucket_override );
+ }
+ }
+
+
+ var vpt = [ 0, 0, 0 ],
+ vpt_cur = 0;
+ function voiPainterAdd( tr, value )
+ {
+ var c = 'sel' + vpt_cur;
+ tr.classList.toggle( c );
+
+ vpt[ vpt_cur ] += ( value * ( tr.classList.contains( c ) ? 1 : -1 ) );
+ vpt[ vpt_cur ] = +( vpt[ vpt_cur ].toFixed( 6 ) );
+
+ showVoiPainter( vpt[ vpt_cur ] );
+ }
+
+
+ var vp_element = null,
+ vpt_dest = [];
+ function showVoiPainter( val )
+ {
+ if ( !vp_element )
+ {
+ vp_element = document.createElement( 'div' );
+ vp_element.id = 'voi-painter';
+
+ for ( var i in vpt )
+ {
+ vpt_dest[ i ] = document.createElement( 'div' );
+ vpt_dest[ i ].classList.add( 'sel' + i );
+ vpt_dest[ i ].innerHTML = '0';
+ vp_element.appendChild( vpt_dest[ i ] );
+
+ ( function( i )
+ {
+ vpt_dest[ i ].addEventListener( 'click', function()
+ {
+ vpt_cur = i;
+ } );
+ } )( i );
+ }
+
+ document.getElementById( 'test-data' ).appendChild( vp_element );
+ }
+
+ vpt_dest[ vpt_cur ] .innerHTML = val;
+ }
+
+
+ return {
+ updateSummaryDebug: updateSummaryDebug,
+
+ onRate: function( callback )
+ {
+ rate_callback = callback;
+ },
+
+ begin: begin,
+ Prior: Prior,
+ };
+} )();
diff --git a/src/current/src/.gitignore b/src/current/src/.gitignore
new file mode 100644
index 00000000..fd9d5a65
--- /dev/null
+++ b/src/current/src/.gitignore
@@ -0,0 +1,6 @@
+# may be copied into the cwd for testing, since it is a dep
+saxon8.jar
+
+*.class
+*.jar
+*.manifest
diff --git a/src/current/src/Makefile b/src/current/src/Makefile
new file mode 100644
index 00000000..2b9d08e6
--- /dev/null
+++ b/src/current/src/Makefile
@@ -0,0 +1,18 @@
+
+dslc_src := $(wildcard com/lovullo/dslc/*.java)
+dslc_bin := $(dslc_src:.java=.class)
+
+.PHONY: dslc clean
+
+dslc: dslc.jar
+
+%.class: %.java
+ javac $<
+
+# we explicitly specify a glob on the path because inner classes are compiled
+# into their own files
+dslc.jar: $(dslc_bin)
+ jar cfm $@ dslc.manifest com/lovullo/dslc/*.class
+
+clean:
+ rm -f $(dslc_bin) dslc.jar
diff --git a/src/current/src/com/lovullo/dslc/DslCompiler.java b/src/current/src/com/lovullo/dslc/DslCompiler.java
new file mode 100644
index 00000000..8747b566
--- /dev/null
+++ b/src/current/src/com/lovullo/dslc/DslCompiler.java
@@ -0,0 +1,303 @@
+
+package com.lovullo.dslc;
+
+import java.io.*;
+import java.util.Map;
+import java.util.HashMap;
+import javax.xml.XMLConstants;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.*;
+import javax.xml.validation.*;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+public class DslCompiler
+{
+ private static class _DslCompiler
+ {
+ private Validator _xsd;
+ private HashMap _xsl;
+
+
+ public _DslCompiler()
+ {
+ _xsd = _createXsd();
+ _xsl = new HashMap();
+ }
+
+
+ public void compile(
+ Source doc,
+ String cmd,
+ String src,
+ String dest,
+ HashMap params
+ ) throws Exception
+ {
+ if ( cmd.equals( "validate" ) )
+ {
+ _xsd.validate( doc );
+ return;
+ }
+ else if ( cmd.equals( "rm" ) )
+ {
+ // remove file (purposely uncaught)
+ ( new File( src ) ).delete();
+
+ return;
+ }
+
+ if ( dest.equals( "" ) )
+ {
+ System.err.printf(
+ "fatal: no destination path provided\n"
+ );
+
+ System.exit( 4 );
+ }
+
+ // transform to dest
+ File destfile = new File( dest );
+ try
+ {
+ _transform(
+ src,
+ doc,
+ cmd,
+ new StreamResult( new File( dest ) ),
+ params
+ );
+ }
+ catch ( Exception e )
+ {
+ // delete the output file; it's garbage
+ destfile.delete();
+
+ // be verbose and unprofessional.
+ throw e;
+ }
+ }
+
+
+ private void _transform(
+ String src,
+ Source doc,
+ String cmd,
+ StreamResult dest,
+ HashMap params
+ ) throws Exception
+ {
+ // load the stylesheet if it has not been already (we load lazily in
+ // case the stylesheet is never needed)
+ if ( !( _xsl.containsKey( cmd ) ) )
+ {
+ _xsl.put( cmd, _createXslt( cmd ) );
+ }
+
+ // since XSL's abstraction does not provide a means to retrieve the
+ // document path (nor does it make sense to), we will pass it in
+ // ourselves, stripped of the file extension
+ String srcpkg = src.substring( 0, src.lastIndexOf( '.' ) );
+
+ // similarily, quickly resolve the relative root path
+ Integer dircount = srcpkg.replaceAll( "[^/]", "" ).length();
+ String relroot = new String( new char[ dircount ] ).replace( "\0", "../" );
+
+ Transformer t = _xsl.get( cmd );
+ t.setParameter( "__srcpkg", srcpkg );
+ t.setParameter( "__relroot", relroot );
+ t.setParameter( "__rseed", (int)( Math.random() * 10e6 ) );
+
+ _setTemplateParams( t, params );
+
+ t.transform( doc, dest );
+ }
+
+
+ private void _setTemplateParams(
+ Transformer t,
+ HashMap params
+ ) throws Exception
+ {
+ for ( Map.Entry param : params.entrySet() )
+ {
+ t.setParameter( param.getKey(), param.getValue() );
+ }
+ }
+
+
+ private Validator _createXsd()
+ {
+ final SchemaFactory factory = SchemaFactory.newInstance(
+ XMLConstants.W3C_XML_SCHEMA_NS_URI
+ );
+
+ // we must disable Unique Particle Attribution (UPC) checking; the
+ // validator used during development did not check for this and it
+ // currently does not pass this test (note that disabling this also
+ // improves the speed of the validator)
+ try
+ {
+ factory.setFeature(
+ "http://apache.org/xml/features/validation/schema-full-checking",
+ false
+ );
+ }
+ catch ( Exception e )
+ {
+ System.err.println(
+ "fatal: cannot disable UPA checking; " +
+ e.getMessage()
+ );
+
+ System.exit( 1 );
+ }
+
+ try
+ {
+ final Schema schema =
+ factory.newSchema( new File( "rater/rater.xsd" ) );
+
+ return schema.newValidator();
+ }
+ catch ( SAXException e )
+ {
+ System.err.printf(
+ "fatal: %s\n",
+ e.getMessage()
+ );
+
+ System.exit( 1 );
+ }
+
+ return null;
+ }
+
+
+ private Transformer _createXslt( String src )
+ {
+ try
+ {
+ final TransformerFactory factory = TransformerFactory.newInstance(
+ "net.sf.saxon.TransformerFactoryImpl", null
+ );
+
+ final Source xsl = new StreamSource( "rater/" + src + ".xsl" );
+
+ return factory.newTransformer( xsl );
+ }
+ catch ( Exception e )
+ {
+ System.err.printf(
+ "fatal: compilation failed; %s\n",
+ e.getMessage()
+ );
+
+ System.exit( 2 );
+ }
+
+ return null;
+ }
+ }
+
+
+
+ public static void main( String[] args ) throws Exception
+ {
+ BufferedReader stdin = new BufferedReader(
+ new InputStreamReader( System.in )
+ );
+
+ String src = ( args.length > 0 ) ? args[0] : "";
+
+ _DslCompiler dslc = new _DslCompiler();
+
+ try
+ {
+ if ( src != "" )
+ {
+ compileSrc( dslc, src );
+ }
+ else
+ {
+ while ( ( src = stdin.readLine() ) != null )
+ {
+ compileSrc( dslc, src );
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ System.err.println(
+ "fatal: I/O error while reading input files: " +
+ e.getMessage()
+ );
+
+ System.exit( 1 );
+ }
+ catch ( Exception e )
+ {
+ System.err.printf(
+ "fatal: `%s': %s\n",
+ src,
+ e.getMessage()
+ );
+
+ // generic exception..ruh roh
+ throw e;
+ }
+ }
+
+
+ private static void compileSrc( _DslCompiler dslc, String cmdline ) throws Exception
+ {
+ System.err.println( cmdline );
+ String[] args = cmdline.split( " " );
+ String dest = "";
+
+ if ( args.length < 2 )
+ {
+ System.err.printf( "fatal: invalid command: %s\n", cmdline );
+ System.exit( 3 );
+ }
+ else if ( args.length >= 3 )
+ {
+ dest = args[2];
+ }
+
+ String cmd = args[0];
+ String src = args[1];
+
+ HashMap params = _getXslParams( args );
+
+ Source doc = new StreamSource( src );
+ dslc.compile( doc, cmd, src, dest, params );
+ }
+
+
+ private static HashMap _getXslParams( String[] args )
+ throws Exception
+ {
+ HashMap params = new HashMap();
+
+ for ( int i = 3; i < args.length; i++ )
+ {
+ String[] keyval = args[ i ].split( "=" );
+
+ if ( keyval.length < 2 )
+ {
+ throw new Exception(
+ "Invalid template param assignment: " +
+ args[ i ]
+ );
+ }
+
+ params.put( keyval[ 0 ], keyval[ 1 ] );
+ }
+
+ return params;
+ }
+}
diff --git a/src/current/standalone.xsl b/src/current/standalone.xsl
new file mode 100644
index 00000000..8ce7f36d
--- /dev/null
+++ b/src/current/standalone.xsl
@@ -0,0 +1,226 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ var rater =
+
+ ;
+
+
+
+
+
+
+ rater.fromMap =
+
+
+
+
+
+
+
+
+ function(d,c){c(d);}
+
+
+ ;
+
+
+ rater._retmap =
+
+
+
+
+
+
+
+
+ function(d,c){c(d);}
+
+
+ ;
+
+
+ module.exports = function( args_base ) {
+ var ret; rater.fromMap( args_base, function( args ) {
+
+ var rater_result = rater( args );
+
+ // perf counter
+ var start = ( new Date() ).getTime();
+
+ rater._retmap( rater_result.vars, function( result )
+ {
+ // add the final premium
+ result.premium = rater_result.premium;
+ result.__classes = rater_result.classes;
+
+ // process the rating worksheet
+ try
+ {
+ result.__worksheet = process_worksheet(
+ rater.worksheet,
+ rater_result.vars,
+ rater_result.consts,
+ rater_result.debug,
+ rater_result.premium
+ );
+ }
+ catch ( e )
+ {
+ result.__worksheet = [ 'Failed: ' + e.message ];
+ }
+ ret = result;
+ } );
+
+ // add performance data
+ var end = ( new Date() ).getTime(),
+ time = ( ( new Date() ).getTime() - start );
+
+ ret.__perf = {
+ time: {
+ start: start,
+ end: end,
+ total: time
+ }
+ };
+
+ } );
+
+ return ret;
+ };
+
+
+ function process_worksheet( worksheet, vars, consts, debug, premium )
+ {
+ var ret = {};
+
+ for ( var name in worksheet )
+ {
+ var data = Array.prototype.slice.call( worksheet[ name ] ),
+ disp = data[0],
+ calc = data[1],
+ always = data[2];
+
+ ret[ name ] = [
+ disp,
+ process_wdisplay_set( [calc], vars, consts, debug ),
+
+ ( ( name === 'yield' )
+ ? premium
+ : ( vars[ name ] || consts[ name ] )
+ ),
+
+ ( always === 'true' )
+ ];
+ }
+
+ return ret;
+ }
+
+ function process_wdisplay( data, vars, consts, debug )
+ {
+ if ( data === null )
+ {
+ return null;
+ }
+
+ var name = data[ 0 ],
+ desc = data[ 1 ],
+ sub = data[ 2 ],
+ val = data[ 3 ]; // may not exist
+
+ return [
+ name,
+ desc,
+ process_wdisplay_set( sub, vars, consts, debug ),
+ val || process_wval( name, desc, vars, consts, debug )
+ ];
+ }
+
+
+ function process_wval( type, desc, vars, consts, debug )
+ {
+ if ( desc.runtime )
+ {
+ type = 'runtime';
+ }
+
+ switch ( type )
+ {
+ case 'apply':
+ case 'cases':
+ case 'case':
+ case 'otherwise':
+ case 'runtime':
+ return ( debug[ desc._id ] );
+
+ case 'value-of':
+ return ( vars[ desc.name ] || consts[ desc.name ] );
+
+ default:
+ return '';
+ }
+ }
+
+
+ function process_wdisplay_set( sub, vars, consts, debug )
+ {
+ var ret = [],
+ i = sub.length;
+
+ while ( i-- )
+ {
+ if ( sub[ i ] === undefined )
+ {
+ continue;
+ }
+
+ ret[ i ] = process_wdisplay( sub[ i ], vars, consts, debug );
+ }
+
+ return ret;
+ }
+
+
+
+ module.exports.rater = rater;
+
+
+
diff --git a/src/current/summary.css b/src/current/summary.css
new file mode 100644
index 00000000..cc878f2b
--- /dev/null
+++ b/src/current/summary.css
@@ -0,0 +1,835 @@
+/**
+ * Rater XML summary stylesheet
+ */
+
+body {
+ /* menu width * menu em + 1 */
+ margin: 0em 0em 0em 13em;
+}
+
+.menu
+{
+ position: fixed;
+ overflow: scroll;
+
+ background-color: #ad7fa8;
+ border-right: 1px solid black;
+
+ top: 0px;
+ left: 0px;
+ bottom: 0px;
+ width: 15em;
+
+ padding: 0.25em;
+
+ font-size: 0.8em;
+
+ resize: horizontal;
+ z-index: 10;
+}
+
+.menu h1
+{
+ font-size: 1.4em;
+ margin-bottom: 0.15em;
+ border-bottom: 1px solid #75507b;
+}
+.menu h1:not(:first-child)
+{
+ margin-top: 2em;
+}
+
+.menu h2
+{
+ font-size: 1.2em;
+ margin-left: 0.5em;
+ margin-bottom: 0.15em;
+}
+
+.menu ul
+{
+ margin: 0px;
+ padding-left: 1.25em;
+ list-style: none;
+}
+
+fieldset,
+.container-param,
+.tcontent
+{
+ display: none;
+}
+fieldset:target,
+.container-param:target,
+.tcontent:target
+{
+ display: block;
+}
+
+fieldset fieldset
+{
+ display: block;
+}
+
+
+#xml-raw:not(.show)
+{
+ display: none;
+}
+
+table > caption
+{
+ font-weight: bold;
+}
+
+dt
+{
+ font-size: 1.1em;
+ font-weight: bold;
+
+ margin-top: 0.5em;
+}
+
+dt.param.classifies {
+ color: green;
+}
+dt.param > .type
+{
+ font-size: 0.8em;
+ font-weight: normal;
+}
+
+dl.params > .default
+{
+ font-size: 0.8em;
+}
+
+table
+{
+ border: 1px solid #888a87;
+ margin: 1em 0px 0px 0px;
+}
+table th
+{
+ border-bottom: 2px solid #888a87;
+ padding: 0.5em;
+}
+table tr > td
+{
+ padding: 0.5em;
+}
+table tr:not(:last-child) > td
+{
+ border-bottom: 1px solid #888a87;
+}
+
+fieldset
+{
+ border: 0px;
+ margin: 0px;
+}
+
+.class .requires,
+.class .name,
+.class .usedby,
+.typedef .type,
+.typedef .name,
+.params .usedby,
+.rate .yields,
+.rate .param,
+.func .param,
+.func .usedby
+{
+ font-size: 0.8em;
+}
+
+.usedby a
+{
+ text-decoration: none;
+}
+
+.calc-order,
+.classifier-calcs
+{
+ max-height: 20em;
+ overflow-y: scroll;
+}
+
+#workstatus
+{
+ position: fixed;
+ display: none;
+
+ background-color: #eeeeec;
+
+ left: 0px;
+ top: 0px;
+ right: auto;
+ padding: 0.25em;
+
+ font-size: 0.9em;
+ border-bottom: 1px solid #babdb6;
+ border-right: 1px solid #babdb6;
+
+ /* entry-form is 2000 */
+ z-index: 1999;
+}
+
+#workstatus.show
+{
+ display: block;
+}
+
+.package
+{
+ background-color: #eeeeec;
+
+ border: 1px solid #babdb6;
+ border-radius: 1em;
+
+ padding: 1em;
+
+ margin-bottom: 3em;
+
+ clear: both;
+}
+.package.devsummary
+{
+ background-color: #ad7fa8;
+ border-color: #75507b;
+}
+
+.package > .title
+{
+ position: relative;
+
+ background-color: #d3d7cf;
+
+ border-bottom: 1px solid #babdb6;
+ border-radius: 1em 1em 0px 0px;
+
+ margin: -1em -1em 0px -1em;
+ padding: 1em;
+}
+.package > .title > h2
+{
+ margin: 0;
+ padding: 0;
+}
+
+.package > h3,
+.package > div > h3
+{
+ border-width: 0px 0px 2px 0px;
+ border-style: solid;
+ border-color: #babdb6;
+
+ margin: 1em -0.9em;
+ padding: 0.1em 0.5em;
+}
+
+.package.us > .title,
+.package.devsummary > .title
+{
+ background-color: #ad7fa8;
+}
+.package.devsummary > .title,
+.package.devsummary > h3,
+.package.devsummary > div > h3
+{
+ border-bottom-color: #75507b;
+}
+
+.package h4.rate-group
+{
+ border-bottom: 1px dashed #babdb6;
+ margin-top: 3em;
+ margin-left: -0.5em;
+}
+.rate-groups .generates
+{
+ font-size: 0.9em;
+}
+
+.package > .title > .imports
+{
+ position: absolute;
+ top: 0px;
+ right: 0px;
+
+ margin: 1.25em;
+}
+.package > .title > .imports::before
+{
+ content: 'Imports: ';
+ font-weight: bold;
+}
+
+body > fieldset
+{
+ position: relative;
+ padding: 5em 0em 0em 0em;
+}
+
+body > fieldset > legend
+{
+ position: absolute;
+ background-color: #eeeeec;
+
+ border-top: 1px solid #babdb6;
+ border-bottom: 1px solid #babdb6;
+
+ padding: 0.5em;
+ left: -0.5em;
+ top: 0em;
+ right: 0px;
+
+ font-size: 1.5em;
+ letter-spacing: 0.1em;
+}
+
+body > fieldset > legend > a.pkg
+{
+ float: right;
+ font-size: 0.5em;
+ line-height: 2.5em;
+
+ color: inherit;
+ border: none;
+ text-decoration: none;
+}
+
+body > fieldset > legend + p.desc
+{
+ margin-top: 0em;
+ font-size: 1.1em;
+}
+
+fieldset.rate > legend > a
+{
+ text-decoration: none;
+ border-bottom: 1px dotted black;
+}
+
+fieldset.rate .classes
+{
+ display: inline-block;
+
+ margin: -1em 0em 2em 0em;
+ padding-bottom: 0.25em;
+
+ font-size: 0.9em;
+ border-bottom: 1px dotted black;
+}
+
+fieldset.rate .classes > .prefix
+{
+ font-variant: small-caps;
+}
+
+/* more than just .rate */
+fieldset .calc-yields
+{
+ font-variant: small-caps;
+}
+
+
+ul.let
+{
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+ul.let li.letequ
+{
+ margin-top: 1em;
+}
+
+ul.let .letdesc
+{
+ font-size: 0.9em;
+ margin-left: 1em;
+}
+
+
+.rate .body,
+.func .body,
+.yield .body
+{
+ float: left;
+}
+.rate .right,
+.func .right,
+.yield .right
+{
+ float: right;
+ padding: 0;
+ margin: 0;
+
+ max-width: 40%;
+}
+.rate .body
+{
+ /** give room for accumulators, depends, etc **/
+ margin-bottom: 5em;
+}
+.right h4
+{
+ border-bottom: 1px solid black;
+
+
+ margin-top: 0;
+ margin-bottom: 0.5em;
+}
+.right > div:not(:first-child)
+{
+ margin-top: 1em;
+}
+.right > .parts.many
+{
+ -webkit-columns: 2;
+ -moz-columns: 2;
+}
+.right > .parts > .part,
+.right > .generators > .generator
+{
+ text-align: center;
+ margin-top: 2em;
+}
+.right > .parts > .part:first-child
+{
+ margin-top: 0em;
+}
+.right > .parts.many > .part
+{
+ /** FF, Webkit and W3C respectively */
+ display: table;
+ -webkit-column-break-inside: avoid;
+ break-inside: avoid-column;
+}
+.right > .parts > .part > .label,
+.right > .generators > .generator > .desc
+{
+ font-size: 0.9em;
+}
+.accum
+{
+ position: absolute;
+ bottom: 1em;
+
+ font-size: 0.9em;
+
+ max-width: 60%;
+}
+
+.error
+{
+ font-weight: bold;
+ color: red;
+}
+
+
+/** entry form **/
+#test-data
+{
+ position: relative;
+}
+#test-data:not(:target)
+{
+ display: none;
+}
+
+form.entry-form
+{
+}
+
+form.entry-form.focus
+}
+
+form.entry-form > dl
+}
+
+form.entry-form.focus > dl
+{
+}
+
+form.entry-form dt
+{
+ clear: left;
+}
+
+form.entry-form .matrix
+{
+ display: inline-block;
+ border: 1px inset;
+ padding: 0.25em;
+
+ float: left;
+ clear: left;
+}
+
+form.entry-form .entry-add
+{
+ float: left;
+ clear: left;
+}
+
+form.entry-form > .foot
+{
+}
+
+form.entry-form > .foot > .ratemsg
+{
+ display: inline-block;
+
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+form.entry-form .final-accept:not(.show),
+form.entry-form .final-premium:not(.show)
+{
+ display: none;
+}
+
+form.entry-form .final-premium
+{
+ margin: 0.25em;
+
+ font-size: 3em;
+ font-weight: bold;
+ color: green;
+
+ text-shadow: 1px 1px 1px black;
+}
+
+
+form.entry-form .final-premium:before
+{
+ content: '$';
+
+ min-height: 0em;
+
+ white-space: nowrap;
+}
+
+
+form.entry-form input[type="reset"]
+{
+ /* help protect against accidental clicks */
+ margin-left: 1em;
+}
+
+form .final-comments
+{
+ background-color: rgba( 255, 255, 255, 0.90 );
+
+ display: none;
+
+ text-align: left;
+
+ padding: 1em;
+}
+form .final-comments.show
+{
+ position: fixed;
+ display: block;
+
+ border: 0.25em solid black;
+
+ top: 0.25em;
+ right: 0.25em;
+ bottom: 0.25em;
+ left: 12.7em;
+}
+
+form .final-comments textarea
+{
+ width: 95%;
+ height: 20em;
+}
+
+form .final-comments button
+{
+ padding: 0.5em 1em;
+ margin-right: 1em;
+}
+
+form .final-comments #final-submit
+{
+ font-weight: bold;
+}
+
+
+/** load dialog **/
+#prior:not(:target)
+{
+ display: none;
+}
+
+.load-dialog td
+{
+ cursor: pointer;
+}
+
+.load-dialog > button
+{
+ margin-top: 0.5em;
+ padding: 0.5em 1em;
+ font-size: 1.1em;
+}
+
+.load-dialog tr > td:first-child,
+.load-dialog tr > td.premium
+{
+ white-space: nowrap;
+}
+
+.load-dialog tr > td.premium,
+.load-dialog tr > td.expected
+{
+ text-align: right;
+}
+
+.load-dialog tr.good
+{
+ background-color: #c0ffc0;
+}
+.load-dialog tr.bad
+{
+ background-color: #ffc0c0;
+}
+.load-dialog tr.good.waiting
+{
+ background-color: #edd400;
+}
+.load-dialog tr.bad.waiting
+{
+ background-color: #f57900;
+}
+.load-dialog tr.changed:not(.skipped)
+{
+ font-weight: bold;
+ font-style: normal !important;
+}
+.load-dialog tr.premchanged
+{
+ font-style: italic;
+}
+.load-dialog tr.skipped
+{
+ background-color: gray;
+}
+
+
+.load-dialog.show
+{
+ display: block;
+}
+
+
+
+.entry-value,
+.entry-value-prior
+{
+ background-color: yellow;
+
+ padding: 0.1em;
+ margin-left: 1em;
+
+ font-weight: bold;
+ color: green;
+}
+.entry-value-prior
+{
+ background-color: purple;
+
+ font-weight: normal;
+ font-size: 0.9em;
+ color: white;
+}
+body:not(.prior) .entry-value-prior
+{
+ display: none;
+}
+
+
+/** validation errors **/
+.validation-errors
+{
+ position: fixed;
+ background-color: #FFAFAF;
+
+ border: 0.5em solid rgba( 255, 0, 0, 0.75 );
+ border-bottom: none;
+
+ bottom: -30.5em;
+ left: 0px;
+ right: 0px;
+
+ padding: 0px 0px 0px 0.5em;
+
+ z-index: 9000;
+}
+
+.validation-errors:hover
+{
+ background-color: white;
+
+ bottom: 0px;
+}
+
+.validation-errors ol
+{
+ height: 30em;
+
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+
+ overflow-y: scroll;
+}
+
+.validation-errors li > .content
+{
+ font-weight: normal;
+}
+
+.nb
+{
+ border-top: 1px solid #babdb6;
+ padding-top: 1em;
+}
+
+
+
+.ultra-breakdown
+{
+ display: block;
+
+ font-size: 0.9em;
+ clear: both;
+}
+
+.ultra-breakdown > h2
+{
+ margin-top: 3em;
+}
+
+.ultra-breakdown + .yields
+{
+ margin-top: 2em;
+}
+
+.ultra-breakdown legend > .uid
+{
+ font-size: 0.8em;
+}
+
+.ultra-breakdown fieldset
+{
+ margin-top: 1em;
+
+ border: 1px solid #babdb6;
+ border-radius: 0.5em;
+}
+
+.ultra-breakdown fieldset:hover
+{
+ border-color: black;
+}
+
+
+.test-summary
+{
+ float: right;
+}
+.test-summary table
+{
+ float: right;
+ clear: both;
+}
+
+#voi-container,
+#class-overview
+{
+ display: none;
+ margin: 0em 0.5em 2em 0em;
+}
+#class-overview td.prior
+{
+ font-size: 0.9em;
+ color: purple;
+}
+body:not(.prior) #class-overview td.prior
+{
+ display: none;
+}
+
+#voi-container.show,
+#class-overview.show
+{
+ display: inline;
+}
+
+#voi-container td.prior
+{
+ font-size: 0.9em;
+ color: purple;
+}
+body:not(.prior) #voi-container td.prior
+{
+ display: none;
+}
+
+.sel0
+{
+ background-color: #ccccff;
+}
+.sel1
+{
+ background-color: #ccffcc;
+}
+.sel2
+{
+ background-color: #ffcccc;
+}
+
+#voi-painter
+{
+ position: fixed;
+ display: block;
+
+ background-color: white;
+ border: 3px solid #eeeeec;
+ border-radius: 0.25em;
+
+ top: -3px;
+ left: 30em;
+
+ font-weight: bold;
+ font-size: 1.3em;
+
+ padding: 0.25em;
+}
+
+#prior-message
+{
+ background-color: #c0ffc0;
+ display: none;
+
+ border: 0.25em solid #4e9a06;
+ width: 50%;
+
+ font-family: monospace;
+
+ padding: 0.5em;
+}
+
+#prior-message.bad
+{
+ background-color: #ffc0c0;
+ border-color: #c00000;
+}
diff --git a/src/current/summary.xsl b/src/current/summary.xsl
new file mode 100644
index 00000000..a59510cb
--- /dev/null
+++ b/src/current/summary.xsl
@@ -0,0 +1,2107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] processing
+
+
+
+ ... (please be patient)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <!DOCTYPE html>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rater/
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] typsetting self...
+
+
+
+
+
+
+
+
+ [summary] typesetting package
+
+ ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Values of Interest
+
+ Name
+ Value
+
+
+
+
+
+
+
+ Classification Overview
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] building package list...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rate Blocks
+
+
+
+
+
+
+
+
+ !!! failed to locate
+
+ source document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+ :
+
+
+
+
+
+
+
+
+ Preprocessor error
+
+
+ (
+
+ )
+
+
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary] [ ]
+
+
+
+ pkg-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [summary]
+
+ for
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /
+
+
+
+
+
+
+
+
+ param
+
+
+
+ classifies
+
+
+
+
+
+ processing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(\in
+
+
+
+ \)
+
+
+ (
+
+
+ #
+
+
+
+
+
+
+
+
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default:
+
+
+
+ {
+
+
+
+
+
+
+
+
+
+ \(\epsilon\)
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+ Value:
+
+
+
+
+
+
+ Too many values; not typesetting.
+
+
+
+
+
+
+ Values:
+ \(\left[\begin{array}\\
+
+
+
+ \\
+
+
+
+
+
+ \end{array}\right]\)
+
+
+
+
+
+ Values:
+ \( \left[ \begin{array}\\
+
+
+ \\
+
+
+
+
+ &
+
+
+
+
+
+ \end{array} \right] \)
+
+
+
+
+
+
+
+ Defined by type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ processing rate group "
+
+ "
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (final premium)
+
+
+
+
+
+
+
+
+
+
+
+
+ processing typedefs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+ Type:
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+ Union of:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+ Value
+ Description
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Base type declaration (defined internally)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ processing classifications
+
+
+
+
+
+
+
+ :class:
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Yields:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ or
+
+
+
+ and
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ warning: failed to locate generated class ref `
+
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ubd-
+
+
+
+
+
+ #
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+ must
+
+
+
+
+ , assuming that:
+
+
+
+
+
+
+
+
+ is ignored during classification
+
+
+
+
+ has the value
+
+
+
+
+
+
+
+
+
+
+
+ match any value in
+
+
+
+
+
+
+ \(
+
+ \) (
+
+
+
+
+ #
+
+
+
+
+
+
+
+ )
+
+
+
+
+
+
+ [Undefined type:
+
+ ]
+
+
+
+
+
+
+
+ match the pattern:
+
+
+
+
+
+
+
+
+ =
+
+
+
+
+
+
+
+
+ be
+
+ \(
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+ processing functions
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+
+
+
+ \;
+
+
+
+ \textrm{
+
+ }
+
+
+
+ \)
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Yields:
+
\(
+
+
+
+
+
+
+
+
\)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Applicability:
+
+
+ Always applicable.
+
+
+
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+
+ but not
+
+
+
+ nor
+
+
+
+
+
+
+
+ [summary] fatal: empty lv:class/@ref!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Yields:
+
\(
+
+
+
+
+
+
+
+
\)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+
+
+
+ [summary] internal: missing TeX symbol for `
+
+ ' within the context of `
+
+ '
+
+
+ ~~~~[begin symbol dump]~~~~
+
+ ~~~~[end symbol dump]~~~~
+
+ ?^!
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Calculation Breakdown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scope boundary (let)
+
+ Each of the "let" statements below are only present
+ within this scope boundary and exist to simplify the equation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ let \(
+
+ \) =
+
+
+
+
+
+
+
+
+
+
+
+
+ ubd-
+
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+
+
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Context-Specific Constants
+
+
+
+
+
+
+
+ Summary Breakdown
+
+
+ parts
+
+
+
+ many
+
+
+
+
+
+
+
+
+
+
+ \(
+
+
+
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Generators
+
+
+
+
+ \(
+ \theta_{
+
+ }
+
+
+ =
+
+ \)
+
+
+
+
+
+
+
+
+ (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \(
+
+ \)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #:class:
+
+
+
+
+
+
+
+
+
+
+ [Undefined classification:
+
+ ]
+
+
+
+
+
+
+
+
+
+
N.B.
+
+ Iverson's Convention
+
+
+ As is customary for many mathematical notations in CS, this system uses
+ Iverson's convention (Iverson's brackets) to denote certain conditional
+ expressions. It should be understood that the notation will produce a
+ value of \( 1 \) if the expression is true; otherwise, it will be
+ strongly \( 0 \) --- that is, even if the expression would
+ be undefined, it will still yield \( 0 \).
+
+
+ \( [ 1 \gt 0 ] = 1 \); \( [ 0 = 1 ] = 0 \); \( [ 5 \textrm{ is prime} ] = 1 \);
+
+
+ \( \sum \limits_{1 \leq k \leq 5} k = \sum \limits_k k [ 1 \leq k \leq 5 ] \)
+
+
+
+ Sets
+
+
+ In the equations represented above, it is to be assumed that undefined
+ values in a set are implicitly 0; this simplifies the representations of
+ the various summations; they are not intended to be vigorous.
+
+
+ For example: let \( x \) = \( \{ 1, 2, 3 \} \). Given the equation \(
+ \sum_k x_k \), it is assumed that the solution is \( 1 + 2 + 3 = 6 \),
+ not undefined. Formally, the former sum is to be interpreted as: \(
+ \sum_{k=0}^n x_k \) where \( n \) is the length of set \( x \), or \(
+ \sum_k x_k [x_k \textrm{ is defined}] \) using Iverson's convention (the
+ latter of which our first notation is based upon by simply omitting the
+ brackets and implying their existence).
+
+
+
+ Counting Sets
+
+ Let \(N(S)\) = the number of values within the set \(S\); this notation is
+ used within certain summations. You may also see the following notations:
+
+
+
+ \(\sum_{k} S_k\) to count the number of one-values in boolean set
+ \(S\) (e.g. if \(S\) denotes properties with swimming pools, we can
+ count the number of swimming pools).
+
+
+ \(\sum_{k=0}^{N(S)} 1\) to count the number of values in set \(S\).
+
+
+
+
+ Vector Arithmetic
+
+ Only one type of vector arithmetic (dot products) is currently supported,
+ but others may be done manually using sums and products. Dot products are
+ denoted by \(a\cdot b\), where \(a\) and \(b\) are vectors.
+
+
+ Subscript Precedence
+
+ Subscripts should be applied from right to left. That is:
+ \(S_{x_{y_z}}\) = \(S_{(x_{(y_z)})}\). In the event where a notation may
+ be ambiguous (e.g. \(\theta_{1_x}\), since \(1_x\) could not possibly make
+ sense in the context of this system), parenthesis will always be added to
+ clarify intent.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ['
+
+ ',
+ 0
+
+
+
+
+ ,'
+
+ '
+
+
+ ],
+
+
+
+ ['
+
+ ',
+ 0
+
+ ],
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Calculation Order (
+
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/tools/csv2xml b/src/current/tools/csv2xml
new file mode 100755
index 00000000..3a5d1b83
--- /dev/null
+++ b/src/current/tools/csv2xml
@@ -0,0 +1,110 @@
+#!/usr/bin/awk -f
+#
+# Compiles the given CSV into a table definition
+
+
+function columngen( header )
+{
+ # output a field constant for each field in the header
+ i = 0
+ while ( field = header[ ++i ] )
+ {
+ printf " \n",
+ field,
+ ( i - 1 ),
+ ( seq[ i ] ) ? "true" : "false"
+ }
+}
+
+
+function seqchk( last )
+{
+ # if there's no last row, then do not bother
+ i = 0
+ while ( i++ < NF )
+ {
+ if ( seq[ i ] == "" ) seq[ i ] = 1
+
+ # this field is sequential if it is greater than or equal to the last field
+ # (we don't check for descending [yet]); note that on the first check, last
+ # will be empty and therefore this check will succeed (properly
+ # initializing seq[i] to 1)
+ seq[ i ] = seq[ i ] && ( $(i) >= last[ i ] )
+ }
+}
+
+
+# header
+BEGIN {
+ rootpath = "../../../"
+ file = ARGV[1]
+
+ # grab only the filename (remove all preceding directories and the file ext)
+ name = gensub( /^.*\/|\.[^.]+$/, "", "g", file )
+
+
+ # output package header
+ printf \
+ "\n" \
+ "\n\n" \
+ " \n\n" \
+ " \n" \
+ " \n\n", \
+ rootpath, name
+
+ # the first row of the CSV is the header representing the column identifiers
+ getline
+ split( $0, header, /,/ )
+
+ # table constant identifier
+ tconst = toupper( gensub( /-/, "_", "g", name ) ) "_RATE_TABLE"
+
+ # generate the header for the table constant
+ printf " \n", name
+
+ printf "%s", " 1 ) ? "," : "" ) $(i)
+ }
+
+ print ";"
+
+ seqchk( last )
+ split( $0, last )
+}
+
+
+# footer
+END {
+ # end of table-rows node
+ print "\" />"
+
+ # columns can't be generated until after we know which ones represent
+ # sequential data
+ columngen( header )
+
+ print " "
+ print " "
+}
diff --git a/src/current/tools/csvi b/src/current/tools/csvi
new file mode 100755
index 00000000..08d80e2a
--- /dev/null
+++ b/src/current/tools/csvi
@@ -0,0 +1,124 @@
+#!/usr/bin/awk -f
+#
+# Performs interpolation for columns in a CSV and outputs the result
+#
+# Configurable values (use -vname=value from command line):
+# step - use predeterminated step instead of calculating from first two rows
+#
+# #
+
+function storeline()
+{
+ for ( i = 1; i <= hlen; i++ ) {
+ prev[i] = $i
+ }
+}
+
+function clearline()
+{
+ for ( i = 1; i <= hlen; i++ ) {
+ prev[i] = 0
+ }
+}
+
+function getprev()
+{
+ for ( i = 1; i <= hlen; i++ ) {
+ $i = prev[i]
+ }
+}
+
+
+function interpolate()
+{
+ lastval = prev[1]
+
+ curval = $1
+ diff = curval - lastval
+
+ # does this value fall in line with the requested step?
+ if ( diff == step )
+ {
+ storeline()
+
+ # we're good; continue
+ print
+ next
+ }
+
+ # if we do not yet have a value large enough to reach our step, then continue
+ # until we do (do not store this line)
+ n = int( diff / step )
+ if ( n <= 0 ) {
+ next
+ }
+
+ # determine interpolation values
+ for ( i = 2; i <= hlen; i++ ) {
+ ival[i] = ( ( $i - prev[i] ) / n )
+ }
+
+ getprev()
+
+ # let us interpolate values that are divisible by the step
+ do
+ {
+ # increase the last value by our step
+ $1 += step
+
+ # interpolate each column value (notice that we skip the first column, which
+ # was handled directly above)
+ for ( i = 2; i <= hlen; i++ ) {
+ $i += ival[i]
+ }
+
+ # print the new line
+ print
+ } while ( ( diff -= step ) > 0 )
+
+ # anything remaining does not fit into our step and will be ignored; we'll
+ # continue with our next step at the next line
+
+ # consider this to be our last line
+ storeline()
+}
+
+
+BEGIN {
+ # the first row of the CSV is the header representing the column identifiers
+ getline
+ hlen = split( $0, header, /,/ )
+
+ # output the header
+ print $0
+
+ # delimit fields by commas (the field separator for CSVs); note that this
+ # won't work properly if strings contain commas
+ FS = OFS = ","
+
+ clearline()
+ getline
+
+ # if no step was provided, then calculate one based on the first two rows
+ if ( step == 0 ) {
+ # output the first row, which does not need to be interpolated
+ print
+
+ # compute the step
+ vala = $1
+ getline
+ valb = $1
+ step = valb - vala
+
+ # since the second line is used to determine the step, then it must match the
+ # step and therefore is good to output
+ print
+
+ # begin.
+ storeline()
+ }
+}
+
+
+# for each row
+{ interpolate() }
diff --git a/src/current/tools/csvm2csv b/src/current/tools/csvm2csv
new file mode 100755
index 00000000..410d9fac
--- /dev/null
+++ b/src/current/tools/csvm2csv
@@ -0,0 +1,112 @@
+#!/usr/bin/awk -f
+#
+# Compiles a "magic" CSV file into a normal CSV
+#
+# "Magic" CSVs simply exist to make life easier: they permit comments, blank
+# lines, variables, sub-delimiter expansion, and any number of ranges per line.
+# Ranges will be expanded in every combination, making rate tables highly
+# maintainable.
+#
+# Variables are also supported when defined using :var=val. Variables may expand
+# into ranges, 'cause they're awesome. Multiple variables may be delimited by
+# semi-colons, as may multiple values.
+#
+# For example:
+# :foo=1--3
+# $foo;7;9--10:$foo, 5--10
+#
+# Would generate:
+# 1, 5
+# 1, 6
+# ...
+# 5, 10
+# 2, 5
+# ...
+# 9, 5
+# ...
+# 1, 5
+# 1, 6
+# ...
+
+
+function rangeout( i, m, j, me, orig )
+{
+ if ( i > NF )
+ {
+ print
+ return
+ }
+
+ orig = $i
+
+ # check first for delimiters
+ if ( match( $i, /^([^;]+);(.*)$/, m ) )
+ {
+ # give it a shot with the first value
+ $i = m[1]
+ rangeout( i )
+
+ # strip off the first value and process with following value(s)
+ $i = m[2]
+ rangeout( i )
+
+ # we've delegated; we're done
+ $i = orig
+ return
+ }
+
+ # attempt to parse variable (may expand into a range)
+ if ( match( $i, /^\$([a-zA-Z_-]+)$/, m ) )
+ {
+ $i = vars[ m[1] ];
+ }
+
+ # parse range
+ if ( match( $i, /^([0-9]+)--([0-9]+)$/, m ) )
+ {
+ j = m[1]
+ me = m[2]
+ do
+ {
+ $i = j
+ rangeout( i + 1 )
+ } while ( j++ < me )
+ }
+ else
+ {
+ rangeout( i + 1 );
+ }
+
+ # restore to original value
+ $i = orig
+}
+
+
+BEGIN {
+ # we're parsing CSVs
+ FS = " *, *"
+ OFS = ","
+}
+
+
+# skip all lines that begin with `#', which denotes a comment, or are empty
+/^#|^$/ { next; }
+
+# lines that begin with a colon are variable definitions
+/^:/ {
+ match( $0, /^:([a-zA-Z_-]+)=(.*?)$/, m )
+ vars[ m[1] ] = m[2]
+ next
+}
+
+# lines containing ranges (denoted by `--', the en dash, which is a typesetting
+# convetion for ranges), sub-delimiters, or variables must be expanded
+/--|;|\$[a-zA-Z_-]/ { rangeout( 1 ); next; }
+
+# all other lines are normal; simply output them verbatim
+{
+ # this assignment will ensure that awk processes the output, ensuring that
+ # extra spaces between commas are stripped
+ $1=$1
+ print
+}
diff --git a/src/current/tools/gen-make b/src/current/tools/gen-make
new file mode 100755
index 00000000..3f59bfea
--- /dev/null
+++ b/src/current/tools/gen-make
@@ -0,0 +1,96 @@
+#!/bin/bash
+#
+# Generates Makefile containing dependencies for each package
+# #
+
+# windows machines may not have the tools to resolve a path, so let's do so
+# ourselves (TODO: there's better (and more performant) ways of doing this than
+# repeated string replacements); TODO: ./
+resolv-path()
+{
+ # no need to do anything if the string does not contain a parent dir reference
+ # (we use this convoluted string replacement check for woe32/64 to prevent
+ # additional spawns (e.g. sed) that would slow us down and because =~ is not
+ # properly supported in msys
+ [[ "$1" != "${1/..\//}"a ]] || {
+ echo "$1"
+ return
+ }
+
+ local path=
+ while read name; do
+ if [ "$name" == .. ]; then
+ [ -n "$path" ] || {
+ echo "warning: will not resolve $1" >&2
+ return 5
+ }
+
+ path="${path%/*}"
+ continue
+ fi
+
+ path="$path/$name"
+ done <<< "${1//\//$'\n'}"
+
+ # echo path without leading /
+ echo -n "${path:1}"
+}
+
+
+# rule for building
+[ -z "$GEN_MAKE" ] && {
+ echo "%.xmlo:: %.tmp"
+ echo -e "\t@rm -f \$@ \$<"
+ [ -n "$xmlo_cmd" ] \
+ && echo -e "\t$xmlo_cmd" \
+ || echo -e "\ttouch \$@"
+
+ echo "%.xmlo:: %.xml | prexmlo"
+ [ -n "$xmlo_cmd" ] \
+ && echo -e "\t$xmlo_cmd" \
+ || echo -e "\ttouch \$@"
+
+ export GEN_MAKE="$( pwd )/$0"
+ exec "$GEN_MAKE" "$@"
+}
+
+until [ $# -eq 0 ]; do (
+ path="${1%%/}"
+ echo "[gen-make] scanning $path" >&2
+
+ cd "$( basename $path )/" || exit $?
+
+ deps=$( find -maxdepth 1 -iname '*.dep' )
+ for dpath in $deps; do
+ # equivalent to basename command; use this since spawning processes on
+ # windoze is slow as shit (originally we did find -exec bashename)
+ d="${dpath##*/}"
+
+ echo "[gen-make] found $path/$d" >&2
+ echo -n "$path/${d%.*}.xmlo:"
+
+ # output deps
+ while read dep; do
+ # if the first character is a slash, then it's relative to the project
+ # root---the resolution has already been done for us!
+ if [ "${dep:0:1}" == '/' ]; then
+ echo -n " ${dep:1}.xmlo"
+ continue
+ fi
+
+ echo -n ' '
+ resolv-path "$path/$dep.xmlo"
+ done < "$d"
+
+ echo
+ done
+
+ # recurse on every subdirectory
+ for p in */; do
+ [ "$p" == ./ -o "$p" == ../ ] && continue
+ [ ! -d "$p" ] || "$GEN_MAKE" "$path/$p" || {
+ echo "fatal: failed to recurse on $( pwd )/$path/$p" >&2
+ exit 1
+ }
+ done
+); shift; done
diff --git a/src/current/tools/lib/zipre.php b/src/current/tools/lib/zipre.php
new file mode 100644
index 00000000..b4f22e1a
--- /dev/null
+++ b/src/current/tools/lib/zipre.php
@@ -0,0 +1,124 @@
+ 3 ) && is_seq( $digits ) )
+ {
+ return sprintf( '[%d-%d]',
+ $digits[ 0 ],
+ $digits[ count( $digits ) - 1 ]
+ );
+ }
+ elseif ( count( $digits ) === 1 )
+ {
+ // if there's only one digit, then that's all we need to return
+ return $digits[ 0 ];
+ }
+
+ return '[' . implode( '', $digits ) . ']';
+ }, $re );
+}
+
+function is_seq( $digits, $last = '' )
+{
+ // stop recursing once we're out of digits
+ if ( count( $digits ) === 0 )
+ {
+ return true;
+ }
+
+ // grab the current digit and remove it from the list (this has the effect
+ // of both cons and cdr)
+ $digit = (int)( array_shift( $digits ) );
+
+ // consider this a sequence if this digit is one more than the last (or if
+ // there is no last digit) and if the following digit is sequential
+ return ( ( $last === '' ) || ( $digit === ( $last + 1) ) )
+ && is_seq( $digits, $digit );
+}
diff --git a/src/current/tools/tdat2xml b/src/current/tools/tdat2xml
new file mode 100755
index 00000000..db4e9b15
--- /dev/null
+++ b/src/current/tools/tdat2xml
@@ -0,0 +1,274 @@
+#!/usr/bin/env php
+
+ ' . "\n";
+ }
+
+ return sprintf(
+ '' .
+ "\n%s" .
+ " %s\n" .
+ "\n \n",
+ $name,
+ gen_identifier( $id ),
+ $desc,
+ $yields,
+ $prev_value,
+ gen_any_block( $queue, $or )
+ );
+}
+
+
+function gen_any_block( $queue, $or )
+{
+ $any = gen_zip_re( $queue ) .
+ gen_on_class( $or );
+
+ return ( $any )
+ ? '' . $any . ' '
+ : '';
+}
+
+
+function gen_zip_re( $data )
+{
+ if ( count( $data ) === 0 )
+ {
+ return '';
+ }
+
+ return sprintf(
+ ' ',
+ gen_re_quick( $data )
+ );
+}
+
+function gen_on_class( $data )
+{
+ if ( count( $data ) === 0 )
+ {
+ return '';
+ }
+
+ $cur = array_shift( $data );
+
+ return sprintf(
+ ' %s',
+ $cur,
+ gen_on_class( $data )
+ );
+}
+
+function gen_identifier( $id )
+{
+ return is_numeric( $id )
+ ? $id
+ : '-' . strtolower( $id );
+}
+
+function gen_identifier_value( $id )
+{
+ // for non-numeric identifiers, return ascii value
+ // of character to represent our value
+ return is_numeric( $id )
+ ? $id
+ : ord( $id );
+}
+
+$file = $argv[ 1 ];
+$fdat = explode( '.', basename( $file ) );
+$name = $fdat[ 0 ];
+
+$cur = '';
+$queue = array();
+$or = array();
+
+$fh = fopen( $file, 'r' );
+
+echo 'name="rates/territories/', $name, '" ', "\n",
+ 'desc="', ucfirst( $name ), ' territory classifications">' . "\n\n";
+
+echo "\n\n";
+
+$ids = array();
+$params = array();
+$imports = array();
+$prev_yields = '';
+$prev_yields_all = array();
+$classes = '';
+
+$param_type = 'terrType' . ucfirst( $name );
+
+while ( true )
+{
+ // read the line within the loop so that we do not terminate until after we
+ // treat eof as an empty line
+ $line = str_replace( array( "\n", "\r" ), '', fgets( $fh ) );
+
+ if ( !$cur )
+ {
+ if ( substr( $line, 0, 12 ) === '@import-pkg ' )
+ {
+ $imports[] = substr( $line, 12 );
+ continue;
+ }
+
+ // we expect this line to be a territory descriptor
+ try
+ {
+ list ( $id, $desc ) = parse_tdesc( $line );
+ }
+ catch ( Exception $e )
+ {
+ fwrite( STDERR, 'Invalid territory descriptor: ' . $line );
+ exit( 1 );
+ }
+
+ $ids[] = $id;
+ $cur = $id;
+ }
+ elseif ( ( $line === '' ) || feof( $fh ) )
+ {
+ // generate param for typedef
+ $params[ $id ] = $desc;
+
+ // if there's nothing in the queue, then treat this as an 'ROS' (this
+ // should appear as the *last* territory, or it will not function as
+ // expected)
+ if ( count( $queue ) === 0 )
+ {
+ $prev = $prev_yields_all;
+ }
+ else
+ {
+ $prev = array( $prev_yields );
+ }
+
+ // generate the classification
+ $classes .= gen_classification( $id, $name, $desc, $prev, $queue, $or );
+
+ // this accomplishes two things: (1) avoids regexes if there's a
+ // previous match and (2) ensures that we cannot possibly match multiple
+ // territories
+ $prev_yields = gen_yields( $id, $name );
+ $prev_yields_all[] = $prev_yields;
+
+ $cur = '';
+ $queue = array();
+ $or = array();
+
+ if ( feof( $fh ) )
+ {
+ break;
+ }
+ }
+ elseif ( $line[0] === '=' )
+ {
+ // =foo means match on classification @yields "foo"
+ $or[] = substr( $line, 1 );
+ }
+ else
+ {
+ $queue[] = $line;
+ }
+}
+
+$param_name = 'territory_' . $name;
+?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $desc ) { ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/current/tools/zipre b/src/current/tools/zipre
new file mode 100755
index 00000000..4e6966f2
--- /dev/null
+++ b/src/current/tools/zipre
@@ -0,0 +1,23 @@
+#!/usr/bin/env php
+
+
+
+
+
+
+
+
+ Root node for rating worksheets
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Package for which worksheet is being generated
+
+
+
+
+
+
+