public override Lazy <object> VisitIndexerExpression(QuestScriptParser.IndexerExpressionContext context)
        {
            //this does necessary type checks.
            var valueType = _scriptEnvironmentBuilder.TypeInferenceVisitor.Visit(context);

            if (valueType == ObjectType.Unknown) //failed at one or more type checks
            {
                return(new Lazy <object>(() => null));
            }

            var instanceType = _scriptEnvironmentBuilder.TypeInferenceVisitor.Visit(context.instance);

            if (instanceType == ObjectType.List)
            {
                return(new Lazy <object>(() =>
                {
                    //we can assume those types are there because we did type checks with TypeInferenceVisitor
                    var listArray = (ArrayList)context.instance.Accept(this).Value.GetValueOrLazyValue();
                    return listArray[int.Parse(context.parameter.Accept(this).Value.GetValueOrLazyValue().ToString())];
                }));
            }

            if (instanceType == ObjectType.Dictionary)
            {
                throw new NotImplementedException("Support for dictionaries is currently not implemented");
            }

            _scriptEnvironmentBuilder.Errors.Add(new UnexpectedTypeException(context, ObjectType.List, instanceType,
                                                                             context.instance,
                                                                             $"Indexer expression must be applied to either list or a dictionary, and this was '{instanceType}'."));
            return(base.VisitIndexerExpression(context));
        }
Example #2
0
        public override ObjectType VisitIndexerExpression(QuestScriptParser.IndexerExpressionContext context)
        {
            var variableType = context.instance.Accept(this);

            if (variableType == ObjectType.List)
            {
                //first verify that the indexer parameter is integer, otherwise
                //in the context of lists the expression makes no sense
                var parameterType = context.parameter.Accept(this);
                if (!TypeUtil.IsNumeric(parameterType))
                {
                    _scriptEnvironmentBuilder.Errors.Add(
                        new UnexpectedTypeException(
                            context, ObjectType.Integer,
                            parameterType,
                            context.parameter,
                            "When using list accessor, the index should be of integer type. For example 'x = list[23]' is a valid statement."));
                    return(ObjectType.Unknown);
                }

                //at this point the expression we are accessing through indexer SHOULD be evaluable,
                //so we are simply resolving it's value sooner
                var value = _scriptEnvironmentBuilder.ValueResolverVisitor.Visit(context.instance).Value
                            .GetValueOrLazyValue();
                var valueAsArray = value as ArrayList;
                if (valueAsArray == null) //precaution, shouldn't happen
                {
                    if (!TypeUtil.TryConvertType(value.GetType(), out var resultingType))
                    {
                        resultingType = ObjectType.Unknown;
                    }

                    _scriptEnvironmentBuilder.Errors.Add(
                        new UnexpectedTypeException(
                            context, ObjectType.List,
                            resultingType,
                            context.parameter,
                            $"Expected {context.instance.GetText()} to be a 'ObjectType.List', but it is '{resultingType}'. Thus, cannot infer the resulting type of the indexer expression"));
                    return(ObjectType.Unknown);
                }

                if (!TypeUtil.TryConvertType(valueAsArray[0].GetType(), out var itemType))
                {
                    itemType = ObjectType.Unknown;
                }

                return(itemType);
            }

            //TODO:Add here support for dictionaries (object attributes and function parameter may be of dictionary type)
            return(ObjectType.Unknown);
        }