public static IEnumerable <PapyrusSymbol> GetKnownParameterValueSymbols(this FunctionCallExpressionNode functionCallExpression, int parameterIndex, out bool valuesAreValidExclusively) { valuesAreValidExclusively = false; var definedFunction = functionCallExpression.GetDefinition(); var parameterDefinition = functionCallExpression.GetParameterDefinition(parameterIndex); #if FALLOUT4 if (parameterDefinition != null) { var parameterTypeName = parameterDefinition.TypeIdentifier.Text; if (parameterTypeName.CaseInsensitiveEquals("CustomEventName")) { valuesAreValidExclusively = true; return(GetKnownEventParameterSymbols <CustomEventSymbol>(functionCallExpression, parameterIndex)); } if (parameterTypeName.CaseInsensitiveEquals("ScriptEventName")) { valuesAreValidExclusively = true; return(GetKnownEventParameterSymbols <EventSymbol>(functionCallExpression, parameterIndex)); } var functionName = definedFunction.Header.Identifier.Text; if (functionName.CaseInsensitiveEquals("FindStruct") || functionName.CaseInsensitiveEquals("RFindStruct")) { if (parameterDefinition.Identifier.Text.CaseInsensitiveEquals("asVarName")) { valuesAreValidExclusively = true; var definedFunctionScriptSymbol = definedFunction.Symbol.Script; var elementTypeId = definedFunctionScriptSymbol.SyntheticArrayType?.ElementType; if (elementTypeId.HasValue) { if (functionCallExpression.GetTypeChecker().GetTypeForObjectId(elementTypeId.Value) is StructType elementType) { return(elementType.Symbol.Children); } } return(Enumerable.Empty <PapyrusSymbol>()); } } } #endif if (definedFunction.Symbol.Name.CaseInsensitiveEquals("GotoState")) { var expressionForScriptType = functionCallExpression.GetMemberAccessExpression()?.BaseExpression; var scriptType = expressionForScriptType?.GetTypeOfExpression() as ScriptType ?? functionCallExpression.Script.Symbol.GetPapyrusType() as ScriptType; return(scriptType.Symbol.GetExtendedScriptChain(true). SelectMany(scriptSymbol => scriptSymbol.Children.OfType <StateSymbol>()). DistinctBy(s => s.Name.ToLower()).ToArray()); } return(Enumerable.Empty <PapyrusSymbol>()); }
public static int GetFunctionParameterIndexAtPosition(this FunctionCallExpressionNode functionCallExpression, Position position) { var intersectingParameterIndex = 0; // Here, we're making the parameter node ranges contiguous var parameterRanges = new List <Range>(); for (var i = 0; i < functionCallExpression.Parameters.Count; i++) { var range = functionCallExpression.Parameters[i].Range; if (i > 0) { var previousParameterEnd = functionCallExpression.Parameters[i - 1].Range.End; range = new Range() { Start = new Position() { Line = previousParameterEnd.Line, Character = previousParameterEnd.Character + 1 }, End = new Position() { Line = range.End.Line, Character = range.End.Character + 1 } }; } parameterRanges.Add(range); } var intersectingRange = parameterRanges.LastOrDefault(r => position >= r.Start); intersectingParameterIndex = parameterRanges.IndexOf(intersectingRange); // If we're intersecting a named call parameter, we want to adjust the index to match the actual signature index. var intersectingCallParameter = functionCallExpression.Parameters.ElementAtOrDefault(intersectingParameterIndex); if (intersectingCallParameter != null) { if (intersectingCallParameter.Identifier != null) { var parameterDefinition = intersectingCallParameter.GetParameterDefinition(); return(functionCallExpression.GetDefinition().Header.Parameters.IndexOf(parameterDefinition)); } } if (intersectingParameterIndex == -1) { intersectingParameterIndex = 0; } return(intersectingParameterIndex); }
public static FunctionParameterNode GetParameterDefinition(this FunctionCallExpressionNode callExpression, int parameterIndex) { var functionDefinition = callExpression.GetDefinition(); if (functionDefinition == null) { return(null); } return(functionDefinition.Header.Parameters.ElementAtOrDefault(parameterIndex)); }
/// <summary> /// 函数调用 /// </summary> /// <param name="node"></param> public void Visit(FunctionCallExpressionNode node) { var builder = new StringBuilder(); builder.Append("函数调用:"); builder.AppendFormat("{0}(", node.FunctionName); foreach (var item in node.Arguments) { builder.Append(item.ToString() + ","); } builder.Replace(",", ")", builder.Length, 1); Console.WriteLine(builder.ToString()); }
private FunctionDeclarationNode GetReferencedFunction(FunctionCallExpressionNode functionCallNode) { var matchedFunctions = Functions.Where(function => function.FunctionName == functionCallNode.FunctionName).ToList(); if (matchedFunctions.Count == 1) { var currentFunction = matchedFunctions[0]; return(currentFunction); } else { throw new UnknownNameError("No function with the given name exists.", functionCallNode.FunctionName); } }
private StatementNode?ParseExpressionStatement(ref int index) { ExpressionNode?expression = expressionParser.ParseNextExpression(ref index); if (expression == null) { return(null); } return(expression switch { FunctionCallExpressionNode functionCall => ParseFunctionCallStatement(functionCall, ref index), IdentifierExpressionNode identifierExpression => ParseVariableAssignmentStatement(ref index, identifierExpression.IdentifierNode, expression), _ => Error(), });
private static IEnumerable <PapyrusSymbol> GetKnownEventParameterSymbols <T>(FunctionCallExpressionNode functionCallExpression, int parameterIndex) where T : PapyrusSymbol { // If the event name parameter is not the first parameter: // We assume that the first parameter's expression result is of the source type. // If it *is* the first parameter: // The defined function most likely lives on ScriptObject, so we need to find the derived type that is the subject of the call. // So, either the source type is the base expression of the parent member access expression, -or-, if there is no member access expression, // then it must be the current script type. var expressionForSourceType = parameterIndex > 0 ? functionCallExpression.Parameters.ElementAtOrDefault(0).Value : functionCallExpression.GetMemberAccessExpression()?.BaseExpression; var sourceType = expressionForSourceType?.GetTypeOfExpression() as ScriptType ?? functionCallExpression.Script.Symbol.GetPapyrusType() as ScriptType; // CustomEventNames can be inherited, so the symbols are sourced from the full extended script chain return(sourceType.Symbol.GetExtendedScriptChain(true).SelectMany(scriptSymbol => scriptSymbol.Children.OfType <T>()).ToArray()); }
private Variable CreateFunctionCall(FunctionCallExpressionNode functionCallNode, FunctionDeclarationNode currentFunction) { //Create function scope variables var functionArgumentVariables = new List <Variable>(); var functionCallArguments = functionCallNode.Arguments.ToList(); var functionSigArguments = currentFunction.Parameters.ToList(); //Create var createdArgumentVariables = functionSigArguments.Zip(functionCallArguments, (sigArg, callArg) => { var outputVariable = new Variable { Name = sigArg.Name, Value = EvaluateExpression(callArg) }; return(outputVariable); }); functionArgumentVariables.AddRange(createdArgumentVariables); FunctionScopeVariables.Push(functionArgumentVariables); if (currentFunction.BodyType == FunctionBodyType.FlameScript) { ExecuteNodes(currentFunction.SubNodes.ToList()); } else if (currentFunction.BodyType == FunctionBodyType.Native) { InvokeNativeFunction(currentFunction); } var returnedVariable = CurrentContextScopeVariables.Where(variable => variable.Name == "$return").ToList()[0]; FunctionScopeVariables.Pop(); return(returnedVariable); }
public static FunctionDefinitionNode GetDefinition(this FunctionCallExpressionNode callExpression) { return((callExpression.Identifier.GetDeclaredOrReferencedSymbol() as FunctionSymbol)?.Definition); }
private Expression EvaluateFunctionCall(FunctionCallExpressionNode node) { var modelExpression = EvaluateScope(node); return(Expression.Call(modelExpression, node.MethodInfo)); }
public override PapyrusType VisitFunctionCallExpression(FunctionCallExpressionNode node) { return(node.Identifier.GetDeclaredOrReferencedSymbol()?.GetPapyrusType()); }
internal FunctionCallStatementNode(FunctionCallExpressionNode expression, int lineNumber, int index) : base(lineNumber, index) { UnderlyingFunctionCallExpressionNode = expression; UnderlyingFunctionCallExpressionNode.ParentNode = this; }
private void EvaluateFunctionCallExpressionNode(FunctionCallExpressionNode node) { emitter.CallMethod(node.MethodInfo); }
private (TypeSymbolNode?, bool) BindInFunctionCall(FunctionCallExpressionNode functionCall, VariableIdentifierMap variableIdentifierMap, bool expressionContext) { if (functionCall.FunctionExpressionNode is not IdentifierExpressionNode identifierExpression) { ErrorProvider.ReportError(ErrorCode.CanOnlyCallFunctions, Compilation, functionCall); return(null, false); } SymbolNode?symbol = GetExpressionSymbol(identifierExpression.Identifier, variableIdentifierMap); if (symbol == null) { ErrorProvider.ReportError(ErrorCode.CantFindIdentifierInScope, Compilation, identifierExpression); return(null, false); } if (symbol is not FunctionSymbolNode functionSymbol) { ErrorProvider.ReportError(ErrorCode.CanOnlyCallFunctions, Compilation, functionCall); return(null, false); } identifierExpression.Bind(symbol); if (expressionContext && functionSymbol.ReturnTypeNode == null) { ErrorProvider.ReportError(ErrorCode.OnlyFunctionWithReturnTypeCanBeExpression, Compilation, functionCall); return(null, false); } if (functionSymbol.ParameterNodes.Count != functionCall.ArgumentNodes.Count) { ErrorProvider.ReportError(ErrorCode.WrongNumberOfArguments, Compilation, functionCall, $"Expected number of arguments: {functionSymbol.ParameterNodes.Count}", $"Provided number of arguments: {functionCall.ArgumentNodes.Count}"); return(null, false); } for (int i = 0; i < functionSymbol.ParameterNodes.Count; i++) { TypeSymbolNode?argumentType = BindInExpression(functionCall.ArgumentNodes[i], variableIdentifierMap); if (argumentType == null) { return(null, false); } if (!TypeIsCompatibleWith(argumentType, functionSymbol.ParameterNodes[i].TypeNode, functionCall.ArgumentNodes[i], out ImplicitConversionSymbolNode? conversion)) { return(null, false); } if (conversion != null) { functionCall.ArgumentNodes[i].SpecifyImplicitConversion(conversion); } } functionCall.Bind(functionSymbol); return(functionSymbol.ReturnTypeNode, true); }