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.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); parametersPushed++; } }
public void InvokeStaticFunction(string className, string functionName, ExpressionList parameters, int line, int column) { SymbolTableEntry cdEntry = SymbolTable.getInstance().lookupGlobal(className.ToLower(), SymbolTable.CLASS); 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.ToLower(), 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.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); return; } if (fdEntry != null && ((FUNCTION_DECLARATION)fdEntry.node).modifiers.Contains(Modifiers.PRIVATE)) { Report.Error(217, functionName, line, column); ilGen.Emit(OpCodes.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); return; } } if (fdEntry == null) { Report.Error(216, functionName, line, column); ilGen.Emit(OpCodes.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); return; } FUNCTION_DECLARATION fd = (FUNCTION_DECLARATION)fdEntry.node; if (!fd.modifiers.Contains(Modifiers.STATIC)) { Report.Error(215, functionName, line, column); ilGen.Emit(OpCodes.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); 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); Visit(expr); // clone if value semantics is desired if (!pd.by_reference && !(expr is REFERENCE)) ilGen.Emit(OpCodes.Call, PHPCoreLang.GetMethod("Clone", new Type[] { PHPMixed })); } // if less parameters actually passed then necessary, pass Null objects instead for (int i = parametersPassedActually; i < fd.parameters.Count; i++) { PARAMETER_DECLARATION pd = (PARAMETER_DECLARATION)fd.parameters[i]; if (pd.default_value == null) Report.Warn(300, System.Convert.ToString(i + 1), line, column); ilGen.Emit(OpCodes.Newobj, PHPNull.GetConstructor(Type.EmptyTypes)); } // ensure parameters passed by reference are variables for (int i = 0; i < parametersPassedActually; i++) { PARAMETER_DECLARATION pd = (PARAMETER_DECLARATION)fd.parameters[i]; Expression variableSupplied = (Expression)parameters.Get(i); if (pd.by_reference || variableSupplied is REFERENCE) if (!(variableSupplied is VARIABLE || variableSupplied is REFERENCE)) Report.Error(301, System.Convert.ToString(i + 1), line, column); } // add function call to call trace ilGen.Emit(OpCodes.Ldstr, cd.name + "->" + fd.name); ilGen.Emit(OpCodes.Call, PHPCoreRuntime.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, PHPCoreRuntime.GetMethod("RemoveFunctionCallFromTrace", Type.EmptyTypes)); }