Пример #1
0
        public override Yarn.IType VisitDeclare_statement(YarnSpinnerParser.Declare_statementContext context)
        {
            string description = Compiler.GetDocumentComments(tokens, context);

            // Get the name of the variable we're declaring
            var    variableContext = context.variable();
            string variableName    = variableContext.GetText();

            // Does this variable name already exist in our declarations?
            var existingExplicitDeclaration = Declarations.Where(d => d.IsImplicit == false).FirstOrDefault(d => d.Name == variableName);

            if (existingExplicitDeclaration != null)
            {
                // Then this is an error, because you can't have two explicit declarations for the same variable.
                string v = $"{existingExplicitDeclaration.Name} has already been declared in {existingExplicitDeclaration.SourceFileName}, line {existingExplicitDeclaration.SourceFileLine}";
                this.diagnostics.Add(new Diagnostic(this.sourceFileName, context, v));
                return(BuiltinTypes.Undefined);
            }

            // Figure out the value and its type
            var constantValueVisitor = new ConstantValueVisitor(context, sourceFileName, Types, ref this.diagnostics);
            var value = constantValueVisitor.Visit(context.value());

            // Did the source code name an explicit type?
            if (context.type != null)
            {
                Yarn.IType explicitType;

                if (KeywordsToBuiltinTypes.TryGetValue(context.type.Text, out explicitType) == false)
                {
                    // The type name provided didn't map to a built-in
                    // type. Look for the type in our Types collection.
                    explicitType = this.Types.FirstOrDefault(t => t.Name == context.type.Text);

                    if (explicitType == null)
                    {
                        // We didn't find a type by this name.
                        string v = $"Unknown type {context.type.Text}";
                        this.diagnostics.Add(new Diagnostic(this.sourceFileName, context, v));
                        return(BuiltinTypes.Undefined);
                    }
                }

                // Check that the type we've found is compatible with the
                // type of the value that was provided - if it doesn't,
                // that's a type error
                if (TypeUtil.IsSubType(explicitType, value.Type) == false)
                {
                    string v = $"Type {context.type.Text} does not match value {context.value().GetText()} ({value.Type.Name})";
                    this.diagnostics.Add(new Diagnostic(this.sourceFileName, context, v));
                    return(BuiltinTypes.Undefined);
                }
            }

            // We're done creating the declaration!
            int positionInFile = context.Start.Line;

            // The start line of the body is the line after the delimiter
            int nodePositionInFile = this.currentNodeContext.BODY_START().Symbol.Line + 1;

            var declaration = new Declaration
            {
                Name           = variableName,
                Type           = value.Type,
                DefaultValue   = value.InternalValue,
                Description    = description,
                SourceFileName = this.sourceFileName,
                SourceNodeName = this.currentNodeName,
                Range          = new Range
                {
                    Start =
                    {
                        Line      = variableContext.Start.Line - 1,
                        Character = variableContext.Start.Column,
                    },
                    End =
                    {
                        Line      = variableContext.Stop.Line - 1,
                        Character = variableContext.Stop.Column + variableContext.GetText().Length,
                    },
                },
                IsImplicit = false,
            };

            this.NewDeclarations.Add(declaration);

            return(value.Type);
        }