internal void EmitHelpers() { CompilationUnit unit = this.CompilationUnit; ILEmitter il = new ILEmitter(DeclareHelperBuilder); IndexedPlace script_context_place = new IndexedPlace(PlaceHolder.Argument, 0); foreach (PhpFunction function in unit.GetDeclaredFunctions()) { if (function.IsDefinite) { CodeGenerator.EmitDeclareFunction(il, script_context_place, function); } } foreach (PhpType type in unit.GetDeclaredTypes()) { if (type.IsDefinite) { // CALL <context>.DeclareType(<type desc>, <name>); type.EmitAutoDeclareOnScriptContext(il, script_context_place); } else if (!type.IsComplete) { if (type.IncompleteClassDeclareMethodInfo != null) { // check whether base class is known at this point of execution, // if so, declare this incomplete class immediately. As PHP does. type.EmitDeclareIncompleteOnScriptContext(il, script_context_place); } } } foreach (GlobalConstant constant in unit.GetDeclaredConstants()) { if (constant.IsDefinite) { var field = constant.RealField; Debug.Assert(field != null); Debug.Assert(field.IsStatic); // CALL <context>.DeclareConstant(<name>, <value>); script_context_place.EmitLoad(il); il.Emit(OpCodes.Ldstr, constant.FullName); il.LoadLiteralBox(constant.Value); //il.Emit(OpCodes.Ldsfld, field); // const field cannot be referenced in IL il.Emit(OpCodes.Call, Methods.ScriptContext.DeclareConstant); } } il.Emit(OpCodes.Ret); }
/// <summary> /// Emit the Script attribute with includes,includers,relativePath and timeStamp info. /// </summary> /// <param name="emitAttributes">Specifies single infos to emit.</param> internal void SetScriptAttribute(ScriptAttributes emitAttributes) { // module to resolve type tokens from: ModuleBuilder real_builder = this.AssemblyBuilder.RealModuleBuilder; // [Script(timeStamp, relativePath)] if ((emitAttributes & ScriptAttributes.Script) != 0) { // construct the [Script] attribute: CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.Script, new object[] { sourceTimestamp.Ticks, CompilationUnit.RelativeSourcePath }); ScriptTypeBuilder.SetCustomAttribute(cab); } // [ScriptIncluders(int[])] if ((emitAttributes & ScriptAttributes.ScriptIncluders) != 0 && CompilationUnit.Includers.Count > 0) { // determine includers type token, remove duplicities: int[] includers = ArrayUtils.Unique(Array.ConvertAll(CompilationUnit.Includers.ToArray(), x => real_builder.GetTypeToken(x.Includer.ScriptBuilder.ScriptType).Token)).ToArray(); // construct the [ScriptIncluders] attribute: CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptIncluders, new object[] { includers }); ScriptTypeBuilder.SetCustomAttribute(cab); } // [ScriptIncludees(int[],byte[])] if ((emitAttributes & ScriptAttributes.ScriptIncludees) != 0 && CompilationUnit.Inclusions.Count > 0) { // determine inclusions type token, group by the token to remove duplicities: var inclusionsGroup = ArrayUtils.Group(CompilationUnit.Inclusions.ToArray(), x => real_builder.GetTypeToken(x.Includee.ScriptClassType).Token); // determine if single includees are at least once included unconditionally: int[] inclusions = new int[inclusionsGroup.Count]; bool[] inclusionsConditionalFlag = new bool[inclusions.Length]; int i = 0; foreach (var includee in inclusionsGroup) { // find any unconditional inclusion to mark this unified inclusion as unconditional inclusionsConditionalFlag[i] = ArrayUtils.LogicalAnd(includee.Value, x => x.IsConditional); // inclusions[i] = includee.Key; ++i; } // construct the [ScriptIncluders] attribute: CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptIncludees, new object[] { inclusions, ScriptIncludeesAttribute.ConvertBoolsToBits(inclusionsConditionalFlag) }); ScriptTypeBuilder.SetCustomAttribute(cab); } // [ScriptDeclares(int[])] if ((emitAttributes & ScriptAttributes.ScriptDeclares) != 0) { List <int> declaredTypesToken = new List <int>(); foreach (PhpType type in CompilationUnit.GetDeclaredTypes()) { if (type.IsComplete && type.RealType != null) { declaredTypesToken.Add(real_builder.GetTypeToken(type.RealType).Token); } } if (declaredTypesToken.Count > 0) { // construct the [ScriptDeclares] attribute: CustomAttributeBuilder cab = new CustomAttributeBuilder(Constructors.ScriptDeclares, new object[] { declaredTypesToken.ToArray() }); ScriptTypeBuilder.SetCustomAttribute(cab); } } }