public void InvokeStaticFunction(string className, string functionName, ExpressionList parameters, int line, int column) { SymbolTableEntry cdEntry = SymbolTable.GetInstance().LookupGlobal(className, SymbolTable.CLASS); // type is defined in an referenced assembly if (cdEntry == null) { Type t = SymbolTable.GetInstance().GetExternalType(className); IlGen.Emit(OpCodes.Ldstr, t.AssemblyQualifiedName); IlGen.Emit(OpCodes.Newobj, typeof(ArrayList).GetConstructor(Type.EmptyTypes)); foreach (Expression expr in parameters) { IlGen.Emit(OpCodes.Dup); Visit(expr); IlGen.Emit(OpCodes.Call, typeof(ArrayList).GetMethod("Add", new Type[] { typeof(object) })); IlGen.Emit(OpCodes.Pop); } IlGen.Emit(OpCodes.Ldstr, functionName); IlGen.Emit(OpCodes.Call, PHPRuntimeCore.GetMethod("InvokeExternalStaticFunction", new Type[] { typeof(string), typeof(ArrayList), typeof(object) })); } // type is defined in script else { CLASS_DECLARATION cd = (CLASS_DECLARATION)cdEntry.Node; CLASS_DECLARATION tmpCD = cd; SymbolTableEntry fdEntry = tmpCD.Scope.Lookup(functionName, SymbolTable.FUNCTION); while (fdEntry == null) { if (tmpCD.Extends == null) break; SymbolTableEntry parentCDEntry = SymbolTable.GetInstance().LookupGlobal(tmpCD.Extends, SymbolTable.CLASS); tmpCD = (CLASS_DECLARATION)parentCDEntry.Node; fdEntry = tmpCD.Scope.Lookup(functionName, SymbolTable.FUNCTION); if (fdEntry != null && !((FUNCTION_DECLARATION)fdEntry.Node).Modifiers.Contains(Modifiers.STATIC)) { Report.Error(215, functionName, line, column); IlGen.Emit(OpCodes.Ldnull); return; } if (fdEntry != null && ((FUNCTION_DECLARATION)fdEntry.Node).Modifiers.Contains(Modifiers.PRIVATE)) { Report.Error(217, functionName, line, column); IlGen.Emit(OpCodes.Ldnull); return; } } if (fdEntry == null) { Report.Error(216, functionName, line, column); IlGen.Emit(OpCodes.Ldnull); return; } FUNCTION_DECLARATION fd = (FUNCTION_DECLARATION)fdEntry.Node; if (!fd.Modifiers.Contains(Modifiers.STATIC)) { Report.Error(215, functionName, line, column); IlGen.Emit(OpCodes.Ldnull); return; } // pass parameters (only as many as needed) int parametersPassedActually = (int)Math.Min(fd.Parameters.Count, parameters.Count()); for (int i = 0; i < parametersPassedActually; i++) { PARAMETER_DECLARATION pd = (PARAMETER_DECLARATION)fd.Parameters[i]; Expression expr = (Expression)parameters.Get(i); // ensure a reference is passed, if a reference is required if (pd.ByReference && !(expr is REFERENCE)) expr = new REFERENCE(expr, expr.Line, expr.Column); // process parameter Visit(expr); } // if less parameters actually passed then necessary, pass nulls instead for (int i = parametersPassedActually; i < fd.Parameters.Count; i++) { PARAMETER_DECLARATION pd = (PARAMETER_DECLARATION)fd.Parameters[i]; if (pd.DefaultValue == null) Report.Warn(300, System.Convert.ToString(i + 1), line, column); IlGen.Emit(OpCodes.Ldnull); } // add function call to call trace IlGen.Emit(OpCodes.Ldstr, CD.Name + "->" + fd.Name); IlGen.Emit(OpCodes.Call, PHPRuntimeCore.GetMethod("AddFunctionCallToTrace", new Type[] { typeof(string) })); // call MethodBuilder mb = fd.MthBld; IlGen.Emit(OpCodes.Call, mb); // remove function call from call trace IlGen.Emit(OpCodes.Call, PHPRuntimeCore.GetMethod("RemoveFunctionCallFromTrace", Type.EmptyTypes)); } }
public void PushParameters(ExpressionList parameters, int number) { int parametersPushed = 0; // push parameters available, until desired number is reached while (parametersPushed < number && parametersPushed < parameters.Count()) Visit(parameters.Get(parametersPushed++)); // if not enough parameters were available, fill up with nulls while (parametersPushed < number) { IlGen.Emit(OpCodes.Ldnull); parametersPushed++; } }