Ejemplo n.º 1
0
        // all we need do is visit the function itself, it will handle everything
        public override int VisitValueFunc(YarnSpinnerParser.ValueFuncContext context)
        {
            Visit(context.function());

            return(0);
        }
Ejemplo n.º 2
0
        public override Yarn.Type VisitValueFunc(YarnSpinnerParser.ValueFuncContext context)
        {
            string functionName = context.function().FUNC_ID().GetText();

            Declaration functionDeclaration = Declarations
                                              .Where(d => d.DeclarationType == Declaration.Type.Function)
                                              .FirstOrDefault(d => d.Name == functionName);

            if (functionDeclaration == null)
            {
                // We don't have a declaration for this function. Create an
                // implicit one.
                functionDeclaration = new Declaration {
                    Name            = functionName,
                    DeclarationType = Declaration.Type.Function,
                    IsImplicit      = true,
                    ReturnType      = Yarn.Type.Undefined,
                    Description     = $"Implicit declaration of function at {sourceFileName}:{context.Start.Line}:{context.Start.Column}",
                    SourceFileName  = sourceFileName,
                    SourceFileLine  = context.Start.Line,
                    SourceNodeName  = currentNodeName,
                    SourceNodeLine  = context.Start.Line - (this.currentNodeContext.BODY_START().Symbol.Line + 1),
                };

                // Create the array of parameters for this function based
                // on how many we've seen in this call. Set them all to be
                // undefined; we'll bind their type shortly.
                functionDeclaration.Parameters = context.function().expression()
                                                 .Select(e => new Declaration.Parameter {
                    Type = Yarn.Type.Undefined
                })
                                                 .ToArray();

                NewDeclarations.Add(functionDeclaration);
            }

            // Check each parameter of the function
            var suppliedParameters = context.function().expression();

            Declaration.Parameter[] expectedParameters = functionDeclaration.Parameters;
            if (suppliedParameters.Length != expectedParameters.Length)
            {
                // Wrong number of parameters supplied
                var parameters = expectedParameters.Length == 1 ? "parameter" : "parameters";
                throw new TypeException(context, $"Function {functionName} expects {expectedParameters.Length} {parameters}, but received {suppliedParameters.Length}", sourceFileName);
            }

            for (int i = 0; i < expectedParameters.Length; i++)
            {
                var suppliedParameter = suppliedParameters[i];

                var expectedType = expectedParameters[i].Type;

                var suppliedType = this.Visit(suppliedParameter);

                if (expectedType == Yarn.Type.Undefined)
                {
                    // The type of this parameter hasn't yet been bound.
                    // Bind this parameter type to what we've resolved the
                    // type to.
                    expectedParameters[i].Type = suppliedType;
                    expectedType = suppliedType;
                }

                if (suppliedType != expectedType)
                {
                    throw new TypeException(context, $"{functionName} parameter {i + 1} expects a {expectedType}, not a {suppliedType}", sourceFileName);
                }
            }

            // Cool, all the parameters check out!

            // Finally, return the return type of this function.
            return(functionDeclaration.ReturnType);
        }