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)); }
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); }