private void CompileInitializationCode()
{
// Initialization code should be executed before any other code (global variables/parameters or root expression)
// For this purpose we insert it as THE FIRST global variable $init (global variables are calculated before global parameters)
// and put all initalization code in it.
// In retail mode global variables are calculated lasely if they don't have side effects.
// To mark $init as variable with side effect we put all code to function and set SideEffect flag on this function.
// ILGen expects that all library functions are sideeffect free. To prevent calls to RegisterDecimalFormat() to be optimized out
// we add results returned from these calls and return them as a result of initialization function.
QilNode init = _f.Int32(0);
// Register all decimal formats, they are needed for format-number()
if (_formatNumberDynamicUsed || IsDebug)
{
bool defaultDefined = false;
foreach (DecimalFormatDecl format in _compiler.DecimalFormats)
{
init = _f.Add(init, _f.InvokeRegisterDecimalFormat(format));
defaultDefined |= (format.Name == DecimalFormatDecl.Default.Name);
}
if (!defaultDefined)
{
init = _f.Add(init, _f.InvokeRegisterDecimalFormat(DecimalFormatDecl.Default));
}
}
// Register all script namespaces
foreach (string scriptNs in _compiler.Scripts.ScriptClasses.Keys)
{
init = _f.Add(init, _f.InvokeCheckScriptNamespace(scriptNs));
}
if (init.NodeType == QilNodeType.Add)
{
QilFunction initFunction = _f.Function(_f.FormalParameterList(), init, /*sideEffects:*/_f.True());
initFunction.DebugName = "Init";
_functions.Add(initFunction);
QilNode initBinding = _f.Invoke(initFunction, _f.ActualParameterList());
if (IsDebug)
{
// In debug mode all variables must have type item*
initBinding = _f.TypeAssert(initBinding, T.ItemS);
}
QilIterator initVar = _f.Let(initBinding);
initVar.DebugName = _nameInit.ToString();
_gloVars.Insert(0, initVar);
}
}