Ejemplo n.º 1
0
        /// <summary>
        /// Emit publically accessible stub that just calls argfull of <paramref name="function"/>.
        /// </summary>
        /// <returns><see cref="MethodInfo"/> of newly created function stub.</returns>
        private MethodInfo/*!*/EmitPhpFunctionPublicStub(ref TypeBuilder publicsContainer, PhpFunction/*!*/function)
        {
            Debug.Assert(function != null);
            Debug.Assert(function.ArgFullInfo != null, "!function.ArgFullInfo");

            if (publicsContainer == null)
            {
                publicsContainer = PureAssemblyBuilder.RealModuleBuilder.DefineType(
                    string.Format("{1}<{0}>",
                        StringUtils.ToClsCompliantIdentifier(Path.ChangeExtension(PureAssemblyBuilder.FileName, "")),
                        QualifiedName.Global.ToString()),
                    TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class | TypeAttributes.SpecialName);
            }

            Type returnType;
            var parameterTypes = function.Signature.ToArgfullSignature(1, out returnType);
            parameterTypes[0] = Types.ScriptContext[0];

            var mi = publicsContainer.DefineMethod(function.GetFullName(), MethodAttributes.Public | MethodAttributes.Static, returnType, parameterTypes);
            var il = new ILEmitter(mi);

            // load arguments
            for (int i = 0; i < parameterTypes.Length; i++)
            {
                if (function.Builder != null)
                    mi.DefineParameter(i + 1, ParameterAttributes.None, function.Builder.ParameterBuilders[i].Name);

                il.Ldarg(i);
            }
            
            // call function.ArgFullInfo
            il.Emit(OpCodes.Call, function.ArgFullInfo);
            
            // .ret
            il.Emit(OpCodes.Ret);

            //
            return mi;
        }
Ejemplo n.º 2
0
		/// <summary>
		/// Called when a <see cref="PHP.Core.AST.FunctionDecl"/> AST node is entered during the emit phase.
		/// </summary>
		/// <param name="function">The function to enter.</param>
		/// <returns><B>true</B> if the function should be emitted, <B>false</B> if it should not be emitted
		/// (an error was emitted instead due to the incorrect declaration).</returns>
        public bool EnterFunctionDeclaration(PhpFunction/*!*/ function)
        {
            return EnterFunctionDeclarationInternal(function, function.QualifiedName);
        }
Ejemplo n.º 3
0
		/// <summary>
		/// Emits call to <see cref="ScriptContext.DeclareFunction"/>.
		/// </summary>
		internal static void EmitDeclareFunction(ILEmitter/*!*/il, IPlace/*!*/scriptContextPlace, PhpFunction/*!*/ function)
        {
            Label lbl_fieldinitialized = il.DefineLabel();

            // private static PhpRoutine <routine>'function = null;
            var attrs = FieldAttributes.Static | FieldAttributes.Private;
            var field = il.TypeBuilder.DefineField(string.Format("<routine>'{0}", function.FullName), typeof(PhpRoutineDesc), attrs);

            // if (<field> == null)
            il.Emit(OpCodes.Ldsfld, field);
            il.Emit(OpCodes.Brtrue, lbl_fieldinitialized);
            {
                // <field> = new PhpRoutineDesc(<attributes>, new RoutineDelegate(null, <delegate>))

                // LOAD <attributes>;
                il.LdcI4((int)function.MemberDesc.MemberAttributes);

                // new RoutineDelegate(null, <delegate>, true)
                il.Emit(OpCodes.Ldnull);
                il.Emit(OpCodes.Ldftn, function.ArgLessInfo);
                il.Emit(OpCodes.Newobj, Constructors.RoutineDelegate);
                il.LoadBool(true);

                // new PhpRoutineDesc:
                il.Emit(OpCodes.Newobj, Constructors.PhpRoutineDesc_Attr_Delegate_Bool);

                // <field> = <STACK>
                il.Emit(OpCodes.Stsfld, field);

                // new PurePhpFunction(<field>, fullName, argfull);   // writes desc.Member
                il.Emit(OpCodes.Ldsfld, field);
                il.Emit(OpCodes.Ldstr, function.FullName);
                CodeGenerator.EmitLoadMethodInfo(il, function.ArgFullInfo/*, AssemblyBuilder.DelegateBuilder*/);
                il.Emit(OpCodes.Newobj, Constructors.PurePhpFunction);
                il.Emit(OpCodes.Pop);
                
            }
            il.MarkLabel(lbl_fieldinitialized);

            // CALL ScriptContent.DeclareFunction(<field>, <name>);
            scriptContextPlace.EmitLoad(il);
            
            // LOAD <field>
            il.Emit(OpCodes.Ldsfld, field);            

            // LOAD <fullName>
            il.Emit(OpCodes.Ldstr, function.FullName);

            //
            il.Emit(OpCodes.Call, Methods.ScriptContext.DeclareFunction);
        }
Ejemplo n.º 4
0
        /// <summary>
		/// Emits call to <see cref="ScriptContext.DeclareFunction"/>.
		/// </summary>
        internal void EmitDeclareFunction(PhpFunction/*!*/ function)
        {
            EmitDeclareFunction(il, ScriptContextPlace, function);
        }
Ejemplo n.º 5
0
		public FunctionDecl(SourceUnit/*!*/ sourceUnit,
            Position position, Position entireDeclarationPosition, ShortPosition headingEndPosition, ShortPosition declarationBodyPosition,
			bool isConditional, Scope scope, PhpMemberAttributes memberAttributes, string/*!*/ name, NamespaceDecl ns,
			bool aliasReturn, List<FormalParam>/*!*/ formalParams, List<FormalTypeParam>/*!*/ genericParams,
			List<Statement>/*!*/ body, List<CustomAttribute> attributes)
			: base(position)
		{
			Debug.Assert(genericParams != null && name != null && formalParams != null && body != null);

			this.name = new Name(name);
			this.ns = ns;
			this.signature = new Signature(aliasReturn, formalParams);
			this.typeSignature = new TypeSignature(genericParams);
			this.attributes = new CustomAttributes(attributes);
			this.body = body;
			this.entireDeclarationPosition = entireDeclarationPosition;
            this.headingEndPosition = headingEndPosition;
            this.declarationBodyPosition = declarationBodyPosition;

			QualifiedName qn = (ns != null) ? new QualifiedName(this.name, ns.QualifiedName) : new QualifiedName(this.name);
			function = new PhpFunction(qn, memberAttributes, signature, typeSignature, isConditional, scope, sourceUnit, position);
			function.WriteUp(typeSignature.ToPhpRoutineSignature(function));

			function.Declaration.Node = this;
		}
Ejemplo n.º 6
0
		/// <summary>
		///	reflect global functions in &lt;Script&gt; class
		/// TODO: consider merging with PhpTypeDesc.FullReflectMethods
		/// </summary>
		/// <param name="functions">Dictionary for functions</param>
        /// <param name="scriptType">The type to reflect from.</param>
        private static void ReflectScriptTypeFunctions(Type scriptType, Dictionary<string, DRoutineDesc> functions)
		{
            MethodInfo[] real_methods = scriptType.GetMethods(DTypeDesc.MembersReflectionBindingFlags);
			Dictionary<string, MethodInfo> argless_stubs = new Dictionary<string, MethodInfo>(real_methods.Length / 3);

			// first pass - fill argless_stubs
			for (int i = 0; i < real_methods.Length; i++)
			{
				MethodInfo info = real_methods[i];
				if ((info.Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.PrivateScope)
				{
					if (PhpFunctionUtils.IsArglessStub(info, null))
					{
						argless_stubs.Add(info.Name, info);
						real_methods[i] = null;
					}
				}
				else real_methods[i] = null; // expunge private scope methods
			}

			// second pass - match argfulls
            foreach (MethodInfo info in real_methods)
            {
                // argfull detection:
                if (info == null || !PhpFunctionUtils.IsArgfullOverload(info, null))
                    continue;

                // TODO: namespaces!!

                if (functions.ContainsKey(info.Name))
                    throw new InvalidOperationException("Function '" + info.Name + "' redeclaration.");   // compilation unit contains more functions with the same name

                // find the argless:
                MethodInfo argless_info = null;
                if (!argless_stubs.TryGetValue(info.Name, out argless_info))
                {
                    // argless has to be generated on-the-fly
                    throw new NotImplementedException("Generating argless stubs for imported PHP types is not yet implemented");
                }

                if (!PhpFunctionUtils.IsRealConditionalDefinition(info.Name))
                {
                    Name name = new Name(info.Name);
                    DRoutineDesc func_desc;
                    PhpMemberAttributes attrs = Enums.GetMemberAttributes(info);

                    // this method has not been populated -> create a new PhpRoutineDesc
                    func_desc = new PhpRoutineDesc(attrs, (RoutineDelegate)Delegate.CreateDelegate(Types.RoutineDelegate, argless_info), true);
                    functions.Add(info.Name, func_desc);

                    //
                    if (func_desc.Member == null)
                    {
                        PhpFunction func = new PhpFunction(new QualifiedName(name), (PhpRoutineDesc)func_desc, info, argless_info);
                        func.WriteUp(PhpRoutineSignature.FromArgfullInfo(func, info));
                        func_desc.Member = func;
                    }
                }
            }
		}