예제 #1
0
        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>());
        }
예제 #2
0
        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);
        }
예제 #3
0
        public static FunctionParameterNode GetParameterDefinition(this FunctionCallExpressionNode callExpression, int parameterIndex)
        {
            var functionDefinition = callExpression.GetDefinition();

            if (functionDefinition == null)
            {
                return(null);
            }

            return(functionDefinition.Header.Parameters.ElementAtOrDefault(parameterIndex));
        }
예제 #4
0
        /// <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());
        }
예제 #5
0
        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(),
            });
예제 #7
0
        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());
        }
예제 #8
0
        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);
        }
예제 #9
0
 public static FunctionDefinitionNode GetDefinition(this FunctionCallExpressionNode callExpression)
 {
     return((callExpression.Identifier.GetDeclaredOrReferencedSymbol() as FunctionSymbol)?.Definition);
 }
예제 #10
0
        private Expression EvaluateFunctionCall(FunctionCallExpressionNode node)
        {
            var modelExpression = EvaluateScope(node);

            return(Expression.Call(modelExpression, node.MethodInfo));
        }
예제 #11
0
 public override PapyrusType VisitFunctionCallExpression(FunctionCallExpressionNode node)
 {
     return(node.Identifier.GetDeclaredOrReferencedSymbol()?.GetPapyrusType());
 }
예제 #12
0
 internal FunctionCallStatementNode(FunctionCallExpressionNode expression, int lineNumber, int index) : base(lineNumber, index)
 {
     UnderlyingFunctionCallExpressionNode            = expression;
     UnderlyingFunctionCallExpressionNode.ParentNode = this;
 }
예제 #13
0
 private void EvaluateFunctionCallExpressionNode(FunctionCallExpressionNode node)
 {
     emitter.CallMethod(node.MethodInfo);
 }
예제 #14
0
        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);
        }