Example #1
0
        public bool IsMatching(StaticIfCondition sc, ResolutionContext ctxt)
        {
            if (conditionsBeingChecked.Contains(sc) || ctxt == null)
            {
                return(false);
            }

            conditionsBeingChecked.Add(sc);
            ISymbolValue v = null;

            /*if (System.Threading.Interlocked.Increment(ref stk) > 5)
             * {
             * }*/
            try
            {
                v = Evaluation.EvaluateValue(sc.Expression, ctxt);

                if (v is VariableValue)
                {
                    v = Evaluation.EvaluateValue(((VariableValue)v).Variable.Initializer, ctxt);
                }
            }
            finally
            {
                conditionsBeingChecked.Remove(sc);
            }
            //System.Threading.Interlocked.Decrement(ref stk);
            return(!Evaluation.IsFalseZeroOrNull(v));            //TODO: Just because the expression evaluation isn't working properly currently, let it return true to have it e.g. in the completion list
        }
Example #2
0
        public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
        {
            var oldV = vp[Variable];

            if (oldV is ArrayValue)
            {
                var av = (ArrayValue)oldV;

                //TODO: Immutability checks

                if (av.IsString)
                {

                }
                else
                {
                    var at = av.RepresentedType as ArrayType;
                    var newElements = new ISymbolValue[av.Elements.Length + (ItemNumber<0 ? 1:0)];
                    av.Elements.CopyTo(newElements, 0);

                    if (!ResultComparer.IsImplicitlyConvertible(value.RepresentedType, at.ValueType))
                        throw new EvaluationException(BaseExpression, value.ToCode() + " must be implicitly convertible to the array's value type!", value);

                    // Add..
                    if (ItemNumber < 0)
                        av.Elements[av.Elements.Length - 1] = value;
                    else // or set the new value
                        av.Elements[ItemNumber] = value;

                    vp[Variable] = new ArrayValue(at, newElements);
                }
            }
            else
                throw new EvaluationException(BaseExpression, "Type of accessed item must be an array", oldV);
        }
Example #3
0
 public TemplateParameterSymbol(TemplateParameter tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null)
     : base(tpn != null ? tpn.Representation : null, AbstractType.Get(typeOrValue), paramIdentifier)
 {
     IsKnowinglyUndetermined = TemplateInstanceHandler.IsNonFinalArgument(typeOrValue);
     this.Parameter          = tpn;
     this.ParameterValue     = typeOrValue as ISymbolValue;
 }
Example #4
0
 public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
 {
     if (vp != null && vp.ev != null)
     {
         vp.ev.EvalError(null, "Cannot assign a value to a static property.", new[] { this, value });
     }
     //TODO: What about array.length?
 }
Example #5
0
        /// <summary>
        /// Removes all variable references by resolving them via the given value provider.
        /// Useful when only the value is of interest, not its container or other things.
        /// </summary>
        public static ISymbolValue GetVariableContents(ISymbolValue v, AbstractSymbolValueProvider vp)
        {
            while (v is VariableValue)
            {
                v = vp[(v as VariableValue).Variable];
            }

            return(v);
        }
Example #6
0
 public TemplateParameterSymbol(ITemplateParameter tp,
                                ISemantic representedTypeOrValue,
                                ISyntaxRegion originalParameterIdentifier = null,
                                DNode parentNode = null)
     : base(new TemplateParameterNode(tp) { Parent = parentNode },
            AbstractType.Get(representedTypeOrValue), originalParameterIdentifier ?? tp)
 {
     this.Parameter      = tp;
     this.ParameterValue = representedTypeOrValue as ISymbolValue;
 }
Example #7
0
        public static bool IsEqual(ISymbolValue l, ISymbolValue r)
        {
            // If they are integral values or pointers, equality is defined as the bit pattern of the type matches exactly
            if (l is PrimitiveValue && r is PrimitiveValue)
            {
                var pv_l = (PrimitiveValue)l;
                var pv_r = (PrimitiveValue)r;

                return pv_l.Value == pv_r.Value && pv_l.ImaginaryPart == pv_r.ImaginaryPart;
            }

            else if(l is AssociativeArrayValue && r is AssociativeArrayValue)
            {
                var aa_l = l as AssociativeArrayValue;
                var aa_r = r as AssociativeArrayValue;

                if(aa_l.Elements == null || aa_l.Elements.Count == 0)
                    return aa_r.Elements == null || aa_r.Elements.Count == 0;
                else if(aa_r.Elements != null && aa_r.Elements.Count == aa_l.Elements.Count)
                {
                    //TODO: Check if each key of aa_l can be found somewhere in aa_r.
                    //TODO: If respective keys are equal, check if values are equal
                    return true;
                }
            }

            else if(l is ArrayValue && r is ArrayValue)
            {
                var av_l = l as ArrayValue;
                var av_r = r as ArrayValue;

                if(av_l.IsString == av_r.IsString)
                {
                    if(av_l.IsString)
                        return av_l.StringValue == av_r.StringValue;
                    else
                    {
                        if(av_l.Elements == null || av_l.Elements.Length == 0)
                            return av_r.Elements == null || av_r.Elements.Length == 0;
                        else if(av_r.Elements != null && av_r.Elements.Length == av_l.Elements.Length)
                        {
                            for(int i = av_l.Elements.Length-1; i != -1; i--)
                            {
                                if(!IsEqual(av_l.Elements[i], av_r.Elements[i]))
                                    return false;
                            }
                            return true;
                        }
                    }
                }
            }

            return false;
        }
Example #8
0
        public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
        {
            var oldV = vp[Variable];

            if (oldV is AssociativeArrayValue)
            {
                if (Key != null)
                {
                    var aa = (AssociativeArrayValue)oldV;

                    int itemToReplace = -1;

                    for (int i = 0; i < aa.Elements.Count; i++)
                    {
                        if (SymbolValueComparer.IsEqual(aa.Elements[i].Key, Key))
                        {
                            itemToReplace = i;
                            break;
                        }
                    }

                    // If we haven't found a matching key, add it to the array
                    var newElements = new KeyValuePair <ISymbolValue, ISymbolValue> [aa.Elements.Count + (itemToReplace == -1 ? 1: 0)];
                    aa.Elements.CopyTo(newElements, 0);

                    if (itemToReplace != -1)
                    {
                        newElements[itemToReplace] = new KeyValuePair <ISymbolValue, ISymbolValue>(newElements[itemToReplace].Key, value);
                    }
                    else
                    {
                        newElements[newElements.Length - 1] = new KeyValuePair <ISymbolValue, ISymbolValue>(Key, value);
                    }

                    // Finally, make a new associative array containing the new elements
                    vp[Variable] = new AssociativeArrayValue(aa.RepresentedType as AssocArrayType, newElements);
                }
                else
                {
                    if (vp.ev != null)
                    {
                        vp.ev.EvalError(null, "Key expression must not be null", Key);
                    }
                }
            }
            else
            {
                if (vp.ev != null)
                {
                    vp.ev.EvalError(null, "Type of accessed item must be an associative array", oldV);
                }
            }
        }
Example #9
0
        public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
        {
            var oldV = vp[Variable];

            if (oldV is ArrayValue)
            {
                var av = (ArrayValue)oldV;

                //TODO: Immutability checks

                if (av.IsString)
                {
                }
                else
                {
                    var at          = av.RepresentedType as ArrayType;
                    var newElements = new ISymbolValue[av.Elements.Length + (ItemNumber < 0 ? 1:0)];
                    av.Elements.CopyTo(newElements, 0);

                    if (!ResultComparer.IsImplicitlyConvertible(value.RepresentedType, at.ValueType))
                    {
                        if (vp.ev != null)
                        {
                            vp.ev.EvalError(null, value.ToCode() + " must be implicitly convertible to the array's value type!", value);
                        }
                        return;
                    }

                    // Add..
                    if (ItemNumber < 0)
                    {
                        av.Elements[av.Elements.Length - 1] = value;
                    }
                    else                     // or set the new value
                    {
                        av.Elements[ItemNumber] = value;
                    }

                    vp[Variable] = new ArrayValue(at, newElements);
                }
            }
            else
            {
                if (vp.ev != null)
                {
                    vp.ev.EvalError(null, "Type of accessed item must be an array", oldV);
                }
            }
        }
        public ISymbolValue Visit(AssignExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);

            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);

            //TODO

            this.rValue = null;

            return(null);
        }
        public ISymbolValue Visit(EqualExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);
            var rValue = this.rValue ?? (x.RightOperand != null ? x.RightOperand.Accept(this) : null);

            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);
            var r = TryGetValue(rValue);

            var isEq = SymbolValueComparer.IsEqual(l, r);

            return(new PrimitiveValue(x.OperatorToken == DTokens.Equal ? isEq : !isEq, x));
        }
Example #12
0
		public void Add (IExpression x, ISymbolValue v, params ISymbolValue[] argumentValues)
		{
			if (x == null || v == null)
				return;
			
			var hashVis = D_Parser.Dom.Visitors.AstElementHashingVisitor.Instance;

			long hash = 0;

			foreach (var arg in argumentValues)
				unchecked {
					hash += arg.Accept (hashVis);	
				}

			cache.Add (v, x, hash);
		}
Example #13
0
        public static bool IsFalseZeroOrNull(ISymbolValue v)
        {
            var pv = v as PrimitiveValue;

            if (pv != null)
            {
                try
                {
                    return(pv.Value == 0m);
                }
                catch { }
            }
            else
            {
                return(v is NullValue);
            }

            return(v != null);
        }
Example #14
0
        ObjectValue CreateObjectValue(ISymbolValue v, IExpression originalExpression, ObjectPath pathOpt, EvaluationOptions evalOptions, IDBacktraceSymbol symbolOpt = null)
        {
            if (v != null)
            {
                try
                {
                    return(v.Accept(new ObjectValueSynthVisitor(this)
                    {
                        evalOptions = evalOptions, OriginalExpression = originalExpression, Path = pathOpt
                    }));
                }
                catch (NotImplementedException) { }
            }

            if (symbolOpt != null)
            {
                return(ObjectValue.CreatePrimitive(this, pathOpt, symbolOpt.TypeName, new Mono.Debugging.Backend.EvaluationResult(symbolOpt.Value), ObjectValueFlags.Variable));
            }

            return(ObjectValue.CreateError(this, pathOpt, "", "Couldn't evaluate expression " + (originalExpression != null ? originalExpression.ToString() : ""), ObjectValueFlags.Error));
        }
Example #15
0
        // Define a symbols value
        public void Define(string symbol, ISymbolValue value, bool canReplace = false)
        {
            if (!canReplace)
            {
                // Check not already defined in an outer scope
                var outerScope = ContainingScope;
                if (outerScope != null && outerScope.IsSymbolDefined(symbol))
                {
                    throw new InvalidOperationException(string.Format("The symbol '{0}' is already defined in an outer scope", symbol));
                }

                // Check if already defined
                ISymbolValue existing;
                if (_symbols.TryGetValue(symbol, out existing))
                {
                    throw new InvalidOperationException(string.Format("Duplicate symbol: '{0}'", symbol));
                }
            }

            // Store it
            _symbols[symbol] = value;
            _weakMatchTable  = null;
        }
Example #16
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dm"></param>
        /// <param name="args"></param>
        /// <param name="baseValueProvider">Required for evaluating missing default parameters.</param>
        public static bool AssignCallArgumentsToIC(DMethod dm, ISymbolValue[] args, AbstractSymbolValueProvider baseValueProvider,
			out Dictionary<DVariable,ISymbolValue> targetArgs)
        {
            targetArgs = new Dictionary<DVariable, ISymbolValue>();
            var argsRemaining = args != null ? args.Length : 0;
            int argu = 0;

            for (int para = 0; para < dm.Parameters.Count; para++)
            {
                var par = dm.Parameters[para] as DVariable;

                if (par.Type is VarArgDecl && argsRemaining > 0)
                {
                    var va_args = new ISemantic[argsRemaining];
                    args.CopyTo(va_args, argu);
                    argsRemaining=0;
                    //TODO: Assign a value tuple to par
                    if (++para < dm.Parameters.Count)
                        return false;
                }

                if (argsRemaining > 0)
                {
                    targetArgs[par] = args[argu++];
                    argsRemaining--;
                }
                else if (par.Initializer != null)
                {
                    targetArgs[par] = Evaluation.EvaluateValue(par.Initializer, baseValueProvider);
                }
                else
                    return false;
            }

            return argsRemaining == 0;
        }
Example #17
0
 public AssocArrayPointer(MemberSymbol assocArrayVariable, ISymbolValue accessedItemKey)
     : base(assocArrayVariable)
 {
     Key = accessedItemKey;
 }
        bool HandleDecl(TemplateTypeParameter parameterRef, ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType)
        {
            if (argumentArrayType == null)
            {
                return(false);
            }

            // Handle key type
            var at = argumentArrayType as ArrayType;

            if ((arrayDeclToCheckAgainst.ClampsEmpty == (at == null)) &&
                (at == null || !at.IsStaticArray || arrayDeclToCheckAgainst.KeyExpression == null))
            {
                return(false);
            }
            bool result;

            if (arrayDeclToCheckAgainst.KeyExpression != null)
            {
                // Remove all surrounding parentheses from the expression
                var x_param = arrayDeclToCheckAgainst.KeyExpression;

                while (x_param is SurroundingParenthesesExpression)
                {
                    x_param = ((SurroundingParenthesesExpression)x_param).Expression;
                }

                var ad_Argument = argumentArrayType.DeclarationOrExpressionBase as ArrayDecl;

                /*
                 * This might be critical:
                 * the [n] part in class myClass(T:char[n], int n) {}
                 * will be seen as an identifier expression, not as an identifier declaration.
                 * So in the case the parameter expression is an identifier,
                 * test if it's part of the parameter list
                 */
                var id = x_param as IdentifierExpression;
                if (id != null && id.IsIdentifier && Contains(id.ValueStringHash))
                {
                    // If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved.
                    ISemantic finalArg = null;

                    if (ad_Argument != null && ad_Argument.KeyExpression != null)
                    {
                        ISymbolValue val = null;
                        int          len = -1;
                        finalArg = TypeDeclarationResolver.ResolveKey(ad_Argument, out len, out val, ctxt);
                        if (val != null)
                        {
                            finalArg = val;
                        }
                    }
                    else
                    {
                        finalArg = argumentArrayType.KeyType;
                    }

                    //TODO: Do a type convertability check between the param type and the given argument's type.
                    // The affected parameter must also be a value parameter then, if an expression was given.

                    // and handle it as if it was an identifier declaration..
                    result = Set(parameterRef, finalArg, id.ValueStringHash);
                }
                else if (ad_Argument != null && ad_Argument.KeyExpression != null)
                {
                    // Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true.
                    result = SymbolValueComparer.IsEqual(arrayDeclToCheckAgainst.KeyExpression, ad_Argument.KeyExpression, new StandardValueProvider(ctxt));
                }
                else
                {
                    result = false;
                }

                if (!result)
                {
                    return(false);
                }
            }
            else if (arrayDeclToCheckAgainst.KeyType != null)
            {
                // If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'),
                // pass that number instead of type 'int' to the check.
                if (argumentArrayType != null && at != null && at.IsStaticArray)
                {
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType,
                                        new PrimitiveValue(D_Parser.Parser.DTokens.Int, (decimal)at.FixedLength, null));
                }
                else
                {
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType);
                }

                if (!result)
                {
                    return(false);
                }
            }

            // Handle inner type
            return(HandleDecl(parameterRef, arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base));
        }
		ISymbolValue EvalConcatenation(CatExpression x, ISymbolValue lValue)
		{
			// In the (not unusual) case that more than 2 arrays/strings shall be concat'ed - process them more efficiently
			var catQueue = new Queue<ISymbolValue>();
			
			var catEx = (x as CatExpression);
			
			catQueue.Enqueue(lValue);
			
			catEx = catEx.RightOperand as CatExpression;
			ISymbolValue r;
			while(catEx != null)
			{
				r = TryGetValue(catEx.LeftOperand != null ? catEx.LeftOperand.Accept(this) : null);
				if(r == null || r is NullValue)
				{
					EvalError(catEx.LeftOperand, "Couldn't be evaluated.");
					return null;
				}
				catQueue.Enqueue(r);
				if(catEx.RightOperand is CatExpression)
					catEx = catEx.RightOperand as CatExpression;
				else
					break;
			}

			var rightOp = (catEx ?? x).RightOperand;
			r = TryGetValue(rightOp != null ? rightOp.Accept(this) : null);
			if(r == null)
			{
				EvalError((catEx ?? x).LeftOperand, "Couldn't be evaluated.");
				return null;
			}
			catQueue.Enqueue(r);
			
			// Notable: If one element is of the value type of the array, the element is added (either at the front or at the back) to the array
			// myString ~ 'a' will append an 'a' to the string
			// 'a' ~ myString inserts 'a' at index 0
			
			// Determine whether we have to build up a string OR a normal list of atomic elements
			bool isString = true;
			ArrayType lastArrayType = null;
			
			foreach(var e in catQueue)
			{
				if(e is AssociativeArrayValue)
				{
					EvalError(x, "Can't concatenate associative arrays", e);
					return null;
				}
				else if(e is ArrayValue)
				{
					if(lastArrayType != null && !ResultComparer.IsEqual(lastArrayType, e.RepresentedType))
					{
						EvalError(x, "Both arrays must be of same type", new[]{lastArrayType, e.RepresentedType});
						return null;
					}
					lastArrayType = e.RepresentedType as ArrayType;
					
					if((e as ArrayValue).IsString)
						continue;
				}
				else if(e is PrimitiveValue)
				{
					var btt = (e as PrimitiveValue).BaseTypeToken;
					if(btt == DTokens.Char || btt == DTokens.Dchar || btt == DTokens.Wchar)
						continue;
				}
				
				isString = false;
			}
			
			if(lastArrayType == null)
			{
				EvalError(x, "At least one operand must be an (non-associative) array. If so, the other operand must be of the array's element type.", catQueue.ToArray());
				return null;
			}
			
			if(isString)
			{
				var sb = new StringBuilder();
				
				while(catQueue.Count != 0)
				{
					var e = catQueue.Dequeue();
					if(e is ArrayValue)
						sb.Append((e as ArrayValue).StringValue);
					else if(e is PrimitiveValue)
						sb.Append((char)((e as PrimitiveValue).Value));
				}
				return new ArrayValue(GetStringType(LiteralSubformat.Utf8), sb.ToString());
			}
			
			
			var elements = new List<ISymbolValue>();
			while(catQueue.Count != 0)
			{
				var e = catQueue.Dequeue();
				
				var av = e as ArrayValue;
				if(av != null)
				{
					if(av.IsString)
						elements.Add(av);
					else if(av.Elements != null)
						elements.AddRange(av.Elements);
					continue;
				}
				
				if(!ResultComparer.IsImplicitlyConvertible(e.RepresentedType, lastArrayType.ValueType, ctxt))
				{
					EvalError(x, "Element with type " + (e.RepresentedType != null ? e.RepresentedType.ToCode() : "") + " doesn't fit into array with type "+lastArrayType.ToCode(), catQueue.ToArray());
					return null;
				}
				
				elements.Add(e);
			}
			
			return new ArrayValue(lastArrayType, elements.ToArray());
		}
Example #20
0
        protected override Tuple <CodeLocation, CodeLocation, string> Process(
            EditorData editorData, bool evaluateUnderneathExpression)
        {
            // codeOffset+1 because otherwise it does not work on the first character
            editorData.CaretOffset++;

            var sr = DResolver.GetScopedCodeObject(editorData);

            if (sr == null)
            {
                return(Tuple.Create(CodeLocation.Empty, CodeLocation.Empty, String.Empty));
            }

            var types = LooseResolution.ResolveTypeLoosely(editorData, sr, out _, true);

            if (editorData.CancelToken.IsCancellationRequested)
            {
                return(Tuple.Create(CodeLocation.Empty, CodeLocation.Empty, String.Empty));
            }
            if (types == null)
            {
                return(Tuple.Create(sr.Location, sr.EndLocation, String.Empty));
            }

            var   tipText = new StringBuilder();
            DNode dn      = null;

            foreach (var t in AmbiguousType.TryDissolve(types))
            {
                var dt = t;
                if (dt is AliasedType at)
                {
                    // jump to original definition if it is not renamed or the caret is on the import
                    var isRenamed = (at.Definition as ImportSymbolAlias)?.ImportBinding?.Alias != null;
                    if (!isRenamed || at.Definition.Location == sr.Location)
                    {
                        dt = at.Base;
                    }
                }
                tipText.Append(NodeToolTipContentGen.Instance.GenTooltipSignature(dt));
                if (dt is DSymbol symbol)
                {
                    dn = symbol.Definition;
                }

                tipText.Append("\a");
            }

            while (tipText.Length > 0 && tipText[tipText.Length - 1] == '\a')
            {
                tipText.Length--;
            }

            if (evaluateUnderneathExpression)
            {
                var ctxt = editorData.GetLooseResolutionContext(LooseResolution.NodeResolutionAttempt.Normal);
                ctxt.Push(editorData);
                try
                {
                    ISymbolValue v = null;
                    if (dn is DVariable var && var.Initializer != null && var.IsConst)
                    {
                        v = Evaluation.EvaluateValue(var.Initializer, ctxt);
                    }
                    if (v == null && sr is IExpression expression)
                    {
                        v = Evaluation.EvaluateValue(expression, ctxt);
                    }
                    if (v != null && !(v is ErrorValue))
                    {
                        var valueStr = " = " + v;
                        if (tipText.Length > valueStr.Length &&
                            tipText.ToString(tipText.Length - valueStr.Length, valueStr.Length) != valueStr)
                        {
                            tipText.Append(valueStr);
                        }
                    }
                }
                catch (Exception e)
                {
                    tipText.Append("\aException during evaluation = ").Append(e.Message);
                }

                ctxt.Pop();
            }

            if (dn != null)
            {
                VDServerCompletionDataGenerator.GenerateNodeTooltipBody(dn, tipText);
            }

            while (tipText.Length > 0 && tipText[tipText.Length - 1] == '\a')
            {
                tipText.Length--;
            }

            return(Tuple.Create(sr.Location, sr.EndLocation, tipText.ToString()));
        }
Example #21
0
        void GetRawCallOverloads(PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out ISymbolValue baseValue,
                                 out TemplateInstanceExpression tix)
        {
            baseExpression = null;
            baseValue      = null;
            tix            = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = E(pac, null, false, false);

                if (vs != null && vs.Length != 0)
                {
                    if (vs[0] is ISymbolValue)
                    {
                        baseValue      = (ISymbolValue)vs[0];
                        baseExpression = new[] { baseValue.RepresentedType };
                    }
                    else if (vs[0] is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)vs[0]).Overloads;
                    }
                    else
                    {
                        baseExpression = TypeDeclarationResolver.Convert(vs);
                    }
                }
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else if (eval)
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                    {
                        baseValue = E(tix = call.PostfixForeExpression as TemplateInstanceExpression, false) as ISymbolValue;
                    }
                    else if (call.PostfixForeExpression is IdentifierExpression)
                    {
                        baseValue = E((IdentifierExpression)call.PostfixForeExpression, false) as ISymbolValue;
                    }
                    else
                    {
                        baseValue = E(call.PostfixForeExpression) as ISymbolValue;
                    }

                    if (baseValue is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    }
                    else if (baseValue != null)
                    {
                        baseExpression = new[] { baseValue.RepresentedType }
                    }
                    ;
                    else
                    {
                        baseExpression = null;
                    }
                }
                else
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                    {
                        baseExpression = GetOverloads(tix = (TemplateInstanceExpression)call.PostfixForeExpression, null, false);
                    }
                    else if (call.PostfixForeExpression is IdentifierExpression)
                    {
                        baseExpression = GetOverloads((IdentifierExpression)call.PostfixForeExpression, false);
                    }
                    else
                    {
                        baseExpression = new[] { AbstractType.Get(E(call.PostfixForeExpression)) }
                    };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
        void GetRawCallOverloads(ResolutionContext ctxt, PostfixExpression_MethodCall call,
                                 out AbstractType[] baseExpression,
                                 out ISymbolValue baseValue,
                                 out TemplateInstanceExpression tix)
        {
            baseValue = null;
            tix       = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = EvalPostfixAccessExpression(this, ctxt, pac, null, false, false);

                baseExpression = TypeDeclarationResolver.Convert(vs);
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                {
                    baseExpression = ExpressionTypeEvaluation.GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                }
                else
                {
                    var fore = call.PostfixForeExpression;
                    if (fore is TemplateInstanceExpression)
                    {
                        ImplicitlyExecute = false;
                        tix = call.PostfixForeExpression as TemplateInstanceExpression;
                    }
                    else if (fore is IdentifierExpression)
                    {
                        ImplicitlyExecute = false;
                    }

                    if (call.PostfixForeExpression != null)
                    {
                        baseValue = call.PostfixForeExpression.Accept(this) as ISymbolValue;
                    }

                    if (baseValue is InternalOverloadValue)
                    {
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    }
                    else if (baseValue != null)
                    {
                        baseExpression = new[] { baseValue.RepresentedType }
                    }
                    ;
                    else
                    {
                        baseExpression = null;
                    }
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
        ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression)
        {
            if (!eval)
                return foreExpression; // Still of the array's type.

            if (!(foreExpression is ArrayValue)){
                EvalError(x.PostfixForeExpression, "Must be an array");
                return null;
            }

            var ar = (ArrayValue)foreExpression;
            var sl = (PostfixExpression_Slice)x;

            // If the [ ] form is used, the slice is of the entire array.
            if (sl.FromExpression == null && sl.ToExpression == null)
                return foreExpression;

            // Make $ operand available
            var arrLen_Backup = ValueProvider.CurrentArrayLength;
            ValueProvider.CurrentArrayLength = ar.Elements.Length;

            var bound_lower = E(sl.FromExpression) as PrimitiveValue;
            var bound_upper = E(sl.ToExpression) as PrimitiveValue;

            ValueProvider.CurrentArrayLength = arrLen_Backup;

            if (bound_lower == null || bound_upper == null){
                EvalError(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type");
                return null;
            }

            int lower = -1, upper = -1;
            try
            {
                lower = Convert.ToInt32(bound_lower.Value);
                upper = Convert.ToInt32(bound_upper.Value);
            }
            catch { EvalError(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type");
                return null;
            }

            if (lower < 0){
                EvalError(sl.FromExpression, "Lower boundary must be greater than 0");return null;}
            if (lower >= ar.Elements.Length){
                EvalError(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length);return null;}
            if (upper < lower){
                EvalError(sl.ToExpression, "Upper boundary must be greater than " + lower);return null;}
            if (upper >= ar.Elements.Length){
                EvalError(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length);return null;}

            var rawArraySlice = new ISymbolValue[upper - lower];
            int j = 0;
            for (int i = lower; i < upper; i++)
                rawArraySlice[j++] = ar.Elements[i];

            return new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice);
        }
Example #24
0
 public AssocArrayPointer(DVariable accessedArray, AssocArrayType arrayType, ISymbolValue accessedItemKey, IExpression baseExpression)
     : base(accessedArray, arrayType, baseExpression)
 {
     Key = accessedItemKey;
 }
Example #25
0
 public static ISymbolValue Execute(DMethod method, ISymbolValue[] arguments, AbstractSymbolValueProvider vp)
 {
     throw new NotImplementedException("CTFE is not implemented yet.");
 }
Example #26
0
 public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
 {
     throw new EvaluationException(BaseExpression, "Cannot assign a value to a static property.", value);
     //TODO: What about array.length?
 }
		public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
		{
			keyVal = null;
			fixedArrayLength = -1;
			AbstractType keyType = null;

			if (ad.KeyExpression != null)
			{
				//TODO: Template instance expressions?
				var id_x = ad.KeyExpression as IdentifierExpression;
				if (id_x != null && id_x.IsIdentifier)
				{
					var id = new IdentifierDeclaration((string)id_x.Value)
					{
						Location = id_x.Location,
						EndLocation = id_x.EndLocation
					};

					keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

					if (keyType != null)
					{
						var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

						if (tt == null ||
							!(tt.Definition is DVariable) ||
							((DVariable)tt.Definition).Initializer == null)
							return keyType;
					}
				}

				try
				{
					keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

					if (keyVal != null)
					{
						// Take the value's type as array key type
						keyType = keyVal.RepresentedType;

						// It should be mostly a number only that points out how large the final array should be
						var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
						if (pv != null)
						{
							fixedArrayLength = System.Convert.ToInt32(pv.Value);

							if (fixedArrayLength < 0)
								ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
						}
						//TODO Is there any other type of value allowed?
					}
				}
				catch { }
			}
			else
			{
				var t = Resolve(ad.KeyType, ctxt);
				ctxt.CheckForSingleResult(t, ad.KeyType);

				if (t != null && t.Length != 0)
					return t[0];
			}

			return keyType;
		}
        /// <summary>
        /// a + b; a - b; etc.
        /// </summary>
        ISymbolValue E_MathOp(OperatorBasedExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);
            var rValue = this.rValue;

            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);

            if (l == null)
            {
                /*
                 * In terms of adding opOverloading later on,
                 * lvalue not being a PrimitiveValue shouldn't be a problem anymore - we simply had to
                 * search the type of l for methods called opAdd etc. and call that method via ctfe.
                 * Finally, return the value the opAdd method passed back - and everything is fine.
                 */

                /*
                 * Also, pointers should be implemented later on.
                 * http://dlang.org/expression.html#AddExpression
                 */

                EvalError(x, "Left value must evaluate to a constant scalar value. Operator overloads aren't supported yet", new[]{lValue});
                return null;
            }

            //TODO: Operator overloading

            // Note: a * b + c is theoretically treated as a * (b + c), but it's needed to evaluate it as (a * b) + c !
            if (x is MulExpression || x is PowExpression)
            {
                try{
                if (x.RightOperand is OperatorBasedExpression && !(x.RightOperand is AssignExpression)) //TODO: This must be true only if it's a math expression, so not an assign expression etc.
                {
                    var sx = (OperatorBasedExpression)x.RightOperand;

                    // Now multiply/divide/mod expression 'l' with sx.LeftOperand
                    try{
                    this.lValue = HandleSingleMathOp(x, l, sx.LeftOperand != null ? sx.LeftOperand.Accept(this) : null, mult);

                    // afterwards, evaluate the operation between the result just returned and the sx.RightOperand.
                    return sx.Accept(this);
                    }catch(DivideByZeroException)
                    {
                        EvalError(sx, "Divide by 0");
                        return null;
                    }
                }

                return HandleSingleMathOp(x, l, TryGetValue(rValue ?? (x.RightOperand != null ? x.RightOperand.Accept(this) : null)), mult);
                }catch(DivideByZeroException)
                {
                    EvalError(x, "Divide by 0");
                    return null;
                }
            }
            else if (x is CatExpression)
            {
                return EvalConcatenation(x as CatExpression, l);
            }

            var r = TryGetValue(rValue ?? (x.RightOperand != null ? x.RightOperand.Accept(this) : null));

            if(r == null){
                EvalError(x, "Right operand must evaluate to a value", new[]{rValue});
                return null;
            }

            /*
             * TODO: Handle invalid values/value ranges.
             */

            if (x is XorExpression)
            {
                return HandleSingleMathOp(x, l,r, (a,b)=>{
                                          	if(EnsureIntegralType(x.LeftOperand,a) && EnsureIntegralType(x.RightOperand,b))
                                                return (long)a.Value ^ (long)b.Value;
                                          	return 0L;
                });
            }
            else if (x is OrExpression)
            {
                return HandleSingleMathOp(x, l, r, (a, b) =>
                {
                    if(EnsureIntegralType(x.LeftOperand,a) && EnsureIntegralType(x.RightOperand,b))
                        return (long)a.Value | (long)b.Value;
                  	return 0L;
                });
            }
            else if (x is AndExpression)
            {
                return HandleSingleMathOp(x, l, r, (a, b) =>
                {
                    if(EnsureIntegralType(x.LeftOperand,a) && EnsureIntegralType(x.RightOperand,b))
                                                return (long)a.Value & (long)b.Value;
                                          	return 0L;
                });
            }
            else if (x is ShiftExpression)
                return HandleSingleMathOp(x, l, r, (a, b) =>
                {
                                          	if(!EnsureIntegralType(x.LeftOperand, a) || !EnsureIntegralType(x.RightOperand, b))
                                          		return 0L;
                    if (b.Value < 0 || b.Value > 31){
                        EvalError(x, "Shift operand must be between 0 and 31", new[]{b});
                        return 0m;
                    }

                    switch(x.OperatorToken)
                    {
                        case DTokens.ShiftLeft:
                            return (long)a.Value << (int)b.Value; // TODO: Handle the imaginary part
                        case DTokens.ShiftRight:
                            return (long)a.Value >> (int)b.Value;
                        case DTokens.ShiftRightUnsigned: //TODO: Find out where's the difference between >> and >>>
                            return (ulong)a.Value >> (int)(uint)b.Value;
                    }

                    EvalError(x, "Invalid token for shift expression", new[]{l,r});
                    return 0m;
                });
            else if (x is AddExpression)
                return HandleSingleMathOp(x, l, r, (a, b, op) =>
                {
                    switch (op.OperatorToken)
                    {
                        case DTokens.Plus:
                            return new PrimitiveValue(a.BaseTypeToken, a.Value + b.Value, x, a.ImaginaryPart + b.ImaginaryPart);
                        case DTokens.Minus:
                            return new PrimitiveValue(a.BaseTypeToken, a.Value - b.Value, x, a.ImaginaryPart - b.ImaginaryPart);
                    }

                    EvalError(x, "Invalid token for add/sub expression", new[]{l,r});
                    return null;
                });

            throw new WrongEvaluationArgException();
        }
        ISymbolValue E_BoolOp(OperatorBasedExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);
            var rValue = this.rValue ?? (x.RightOperand != null ? x.RightOperand.Accept(this) : null);

            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);
            var r = TryGetValue(rValue);

            if (x is OrOrExpression)
            {
                // The OrOrExpression evaluates its left operand.
                // If the left operand, converted to type bool, evaluates to true,
                // then the right operand is not evaluated. If the result type of the OrOrExpression
                // is bool then the result of the expression is true.
                // If the left operand is false, then the right operand is evaluated.
                // If the result type of the OrOrExpression is bool then the result
                // of the expression is the right operand converted to type bool.
                return new PrimitiveValue(!(IsFalseZeroOrNull(l) && IsFalseZeroOrNull(r)), x);
            }
            else if (x is AndAndExpression)
                return new PrimitiveValue(!IsFalseZeroOrNull(l) && !IsFalseZeroOrNull(r), x);
            else if (x is IdentityExpression)
            {
                // http://dlang.org/expression.html#IdentityExpression
            }
            else if (x is RelExpression)
            {
                return HandleSingleMathOp(x, l, r, (a,b, op) => {

                    // Unordered-ness is when at least one operator is Not any Number (NaN)
                    bool unordered = a.IsNaN || b.IsNaN;

                    bool relationIsTrue=false;
                    bool cmpIm = a.ImaginaryPart != 0 || b.ImaginaryPart != 0;

                    switch(x.OperatorToken)
                    {
                        case DTokens.GreaterThan: // greater, >
                            relationIsTrue = a.Value > b.Value && (!cmpIm || a.ImaginaryPart > b.ImaginaryPart);
                            break;
                        case DTokens.GreaterEqual: // greater or equal, >=
                            relationIsTrue = a.Value >= b.Value && a.ImaginaryPart >= b.ImaginaryPart;
                            break;
                        case DTokens.LessThan: // less, <
                            relationIsTrue = a.Value < b.Value && (!cmpIm || a.ImaginaryPart < b.ImaginaryPart);
                            break;
                        case DTokens.LessEqual: // less or equal, <=
                            relationIsTrue = a.Value <= b.Value && a.ImaginaryPart <= b.ImaginaryPart;
                            break;
                        case DTokens.Unordered: // unordered, !<>=
                            relationIsTrue = unordered;
                            break;
                        case DTokens.LessOrGreater: // less or greater, <>
                            relationIsTrue = (a.Value < b.Value || a.Value > b.Value) && (!cmpIm || (a.ImaginaryPart < b.ImaginaryPart || a.ImaginaryPart > b.ImaginaryPart));
                            break;
                        case DTokens.LessEqualOrGreater: // less, equal, or greater, <>=
                            relationIsTrue = (a.Value < b.Value || a.Value >= b.Value) && (!cmpIm || (a.ImaginaryPart < b.ImaginaryPart || a.ImaginaryPart >= b.ImaginaryPart));
                            break;
                        case DTokens.UnorderedOrGreater: // unordered or greater, !<=
                            relationIsTrue = unordered || (a.Value > b.Value && (!cmpIm || a.ImaginaryPart > b.ImaginaryPart));
                            break;
                        case DTokens.UnorderedGreaterOrEqual: // unordered, greater, or equal, !<
                            relationIsTrue = unordered || (a.Value >= b.Value && a.ImaginaryPart >= b.ImaginaryPart);
                            break;
                        case DTokens.UnorderedOrLess: // unordered or less, !>=
                            relationIsTrue = unordered || (a.Value < b.Value && (!cmpIm || a.ImaginaryPart < b.ImaginaryPart));
                            break;
                        case DTokens.UnorderedLessOrEqual: // unordered, less, or equal, !>
                            relationIsTrue = unordered || (a.Value <= b.Value && a.ImaginaryPart <= b.ImaginaryPart);
                            break;
                        case DTokens.UnorderedOrEqual: // unordered or equal, !<>
                            relationIsTrue = unordered || (a.Value == b.Value && a.ImaginaryPart == b.ImaginaryPart);
                            break;
                    }

                    return new PrimitiveValue(relationIsTrue, op);
                }, false);
            }

            EvalError(x, "Wrong expression");
            return null;
        }
        void GetRawCallOverloads(PostfixExpression_MethodCall call, 
			out AbstractType[] baseExpression, 
			out ISymbolValue baseValue, 
			out TemplateInstanceExpression tix)
        {
            baseExpression = null;
            baseValue = null;
            tix = null;

            if (call.PostfixForeExpression is PostfixExpression_Access)
            {
                var pac = (PostfixExpression_Access)call.PostfixForeExpression;
                tix = pac.AccessExpression as TemplateInstanceExpression;

                var vs = E(pac, null, false, false);

                if (vs != null && vs.Length != 0)
                {
                    if (vs[0] is ISymbolValue)
                    {
                        baseValue = (ISymbolValue)vs[0];
                        baseExpression = new[] { baseValue.RepresentedType };
                    }
                    else if (vs[0] is InternalOverloadValue)
                        baseExpression = ((InternalOverloadValue)vs[0]).Overloads;
                    else
                        baseExpression = TypeDeclarationResolver.Convert(vs);
                }
            }
            else
            {
                // Explicitly don't resolve the methods' return types - it'll be done after filtering to e.g. resolve template types to the deduced one
                var optBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;

                if (call.PostfixForeExpression is TokenExpression)
                    baseExpression = GetResolvedConstructorOverloads((TokenExpression)call.PostfixForeExpression, ctxt);
                else if (eval)
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                        baseValue = E(tix = call.PostfixForeExpression as TemplateInstanceExpression, false) as ISymbolValue;
                    else if (call.PostfixForeExpression is IdentifierExpression)
                        baseValue = E((IdentifierExpression)call.PostfixForeExpression, false) as ISymbolValue;
                    else
                        baseValue = E(call.PostfixForeExpression) as ISymbolValue;

                    if (baseValue is InternalOverloadValue)
                        baseExpression = ((InternalOverloadValue)baseValue).Overloads;
                    else if (baseValue != null)
                        baseExpression = new[] { baseValue.RepresentedType };
                    else baseExpression = null;
                }
                else
                {
                    if (call.PostfixForeExpression is TemplateInstanceExpression)
                        baseExpression = GetOverloads(tix = (TemplateInstanceExpression)call.PostfixForeExpression, null, false);
                    else if (call.PostfixForeExpression is IdentifierExpression)
                        baseExpression = GetOverloads(call.PostfixForeExpression as IdentifierExpression, deduceParameters:false);
                    else
                        baseExpression = new[] { AbstractType.Get(E(call.PostfixForeExpression)) };
                }

                ctxt.CurrentContext.ContextDependentOptions = optBackup;
            }
        }
        static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore,
                                          MemberSymbol ms, ref AbstractType untemplatedMethod)
        {
            var dm = ms.Definition as DMethod;

            if (dm == null)
            {
                return;
            }



            ISemantic firstUfcsArg;
            bool      isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg);

            // In the case of an ufcs, insert the first argument into the CallArguments list
            if (isUfcs && !hasHandledUfcsResultBefore)
            {
                callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg);
                hasHandledUfcsResultBefore = true;
            }
            else if (!isUfcs && hasHandledUfcsResultBefore)             // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again
            {
                callArguments.RemoveAt(0);
                hasHandledUfcsResultBefore = false;
            }

            if (dm.Parameters.Count == 0 && callArguments.Count > 0)
            {
                return;
            }

            var deducedTypeDict        = new DeducedTypeDictionary(ms);
            var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt);

            var back = ctxt.ScopedBlock;

            using (ctxt.Push(ms))
            {
                if (ctxt.ScopedBlock != back)
                {
                    ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict;
                }

                bool add        = true;
                int  currentArg = 0;
                if (dm.Parameters.Count > 0 || callArguments.Count > 0)
                {
                    bool hadDTuples = false;
                    for (int i = 0; i < dm.Parameters.Count; i++)
                    {
                        var paramType = dm.Parameters[i].Type;

                        // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way..
                        if (paramType is IdentifierDeclaration &&
                            (hadDTuples |= TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg)))
                        {
                            continue;
                        }
                        else if (currentArg < callArguments.Count)
                        {
                            if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++])))
                            {
                                break;
                            }
                        }
                        else
                        {
                            // If there are more parameters than arguments given, check if the param has default values
                            add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null;

                            // Assume that all further method parameters do have default values - and don't check further parameters
                            break;
                        }
                    }

                    // Too few args
                    if (!hadDTuples && currentArg < callArguments.Count)
                    {
                        add = false;
                    }
                }

                if (!add)
                {
                    return;
                }

                // If type params were unassigned, try to take the defaults
                if (dm.TemplateParameters != null)
                {
                    foreach (var tpar in dm.TemplateParameters)
                    {
                        if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null))
                        {
                            return;
                        }
                    }
                }

                if (deducedTypeDict.AllParamatersSatisfied)
                {
                    ms.DeducedTypes = deducedTypeDict.ToReadonly();
                    var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base;

                    if (eval || !returnBaseTypeOnly)
                    {
                        bt = new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes)
                        {
                            Tag = ms.Tag
                        }
                    }
                    ;

                    if (dm.TemplateParameters == null || dm.TemplateParameters.Length == 0)
                    {
                        untemplatedMethod = bt;                         //ISSUE: Have another state that indicates an ambiguous non-templated method matching.
                    }
                    argTypeFilteredOverloads.Add(bt);
                }
            }
        }
		public static ISymbolValue Execute(MemberSymbol method, ISymbolValue[] arguments, AbstractSymbolValueProvider vp)
		{
			return new ErrorValue(new EvaluationException("CTFE is not implemented yet."));
		}
Example #33
0
        /// <summary>
        /// Evaluates the identifier/template instance as usual.
        /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer.
        /// 
        /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned
        /// that keeps all overloads passed via 'overloads'
        /// </summary>
        ISemantic TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments=null)
        {
            if (overloads == null || overloads.Length == 0){
                EvalError(idOrTemplateInstance, "No symbols found");
                return null;
            }

            var r = overloads[0];
            const string ambigousExprMsg = "Ambiguous expression";

            if(r is TemplateParameterSymbol)
            {
                var tps = (TemplateParameterSymbol)r;

                if((tps.Parameter is TemplateTypeParameter ||
                    tps.Parameter is TemplateAliasParameter))
                    return new TypeValue(tps.Base ?? tps);
                if(tps.Parameter is TemplateValueParameter)
                    return tps.ParameterValue;
                if(tps.Parameter is TemplateTupleParameter)
                    return new TypeValue(tps.Base);
                //TODO: Are there other evaluable template parameters?
            }
            else if (r is UserDefinedType || r is PackageSymbol || r is ModuleSymbol || r is AliasedType)
            {
                if (overloads.Length > 1)
                {
                    EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                    return null;
                }
                return new TypeValue(r);
            }
            else if (r is MemberSymbol)
            {
                var mr = (MemberSymbol)r;

                // If we've got a function here, execute it
                if (mr.Definition is DMethod)
                {
                    if (ImplicitlyExecute)
                    {
                        if (overloads.Length > 1){
                            EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                            return null;
                        }
                        return FunctionEvaluation.Execute(mr, executionArguments, ValueProvider);
                    }

                    return new InternalOverloadValue(overloads);
                }
                else if (mr.Definition is DVariable)
                {
                    if (overloads.Length > 1)
                    {
                        EvalError(idOrTemplateInstance, ambigousExprMsg, overloads);
                        return null;
                    }
                    return new VariableValue(mr);
                }
            }

            EvalError(idOrTemplateInstance, "Could neither execute nor evaluate symbol value", overloads);
            return null;
        }
 public static bool IsEqual(ISymbolValue val_x1, ISymbolValue val_x2)
 {
     //TODO
     return val_x1 != null && val_x2 != null && val_x1.ToString() == val_x2.ToString();
 }
Example #35
0
        /// <summary>
        /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b).
        /// if <param name="EvalAndFilterOverloads"></param> is false.
        /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned
        /// which stores the return value of the property function b that is executed without arguments.
        /// Also handles UFCS - so if filtering is wanted, the function becom
        /// </summary>
        ISemantic[] E(PostfixExpression_Access acc,
                      ISemantic resultBase = null, bool EvalAndFilterOverloads = true, bool ResolveImmediateBaseType = true)
        {
            if (acc == null)
            {
                return(null);
            }

            var baseExpression = resultBase ?? E(acc.PostfixForeExpression);

            if (acc.AccessExpression is NewExpression)
            {
                /*
                 * This can be both a normal new-Expression as well as an anonymous class declaration!
                 */
                //TODO!
                return(null);
            }


            AbstractType[] overloads;
            var            optBackup = ctxt.CurrentContext.ContextDependentOptions;

            if (acc.AccessExpression is TemplateInstanceExpression)
            {
                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                var tix = (TemplateInstanceExpression)acc.AccessExpression;
                // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments!
                overloads = GetOverloads(tix, new[] { AbstractType.Get(baseExpression) }, EvalAndFilterOverloads);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }

            else if (acc.AccessExpression is IdentifierExpression)
            {
                var id = acc.AccessExpression as IdentifierExpression;

                if (eval && EvalAndFilterOverloads && resultBase != null)
                {
                    var staticPropResult = StaticProperties.TryEvalPropertyValue(ValueProvider, resultBase, id.ValueStringHash);
                    if (staticPropResult != null)
                    {
                        return new[] { staticPropResult }
                    }
                    ;
                }

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.DontResolveBaseTypes;
                }

                overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id.ValueStringHash, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression);

                if (!ResolveImmediateBaseType)
                {
                    ctxt.CurrentContext.ContextDependentOptions = optBackup;
                }
            }
            else
            {
                if (eval)
                {
                    EvalError(acc, "Invalid access expression");
                    return(null);
                }
                ctxt.LogError(acc, "Invalid post-dot expression");
                return(null);
            }

            /*
             * Try to get ufcs functions at first!
             *
             * void foo(int i) {}
             *
             * class A
             * {
             *	void foo(int i, int a) {}
             *
             *	void bar(){
             *		123.foo(23); // Not allowed!
             *		// Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels,
             *		// it would return the local foo() only, not the global one..which would be an error then!
             *  }
             *
             * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones?
             * }
             */
            if (overloads == null || EvalAndFilterOverloads)
            {
                var oo = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[];

                if (oo != null)
                {
                    int overloadsLength = overloads == null ? 0 : overloads.Length;
                    var newArr          = new AbstractType[overloadsLength + oo.Length];
                    if (overloadsLength != 0)
                    {
                        overloads.CopyTo(newArr, 0);
                    }
                    oo.CopyTo(newArr, overloadsLength);
                    overloads = newArr;
                }
            }

            // If evaluation active and the access expression is stand-alone, return a single item only.
            if (EvalAndFilterOverloads && eval)
            {
                return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) }
            }
            ;

            return(overloads);
        }

        ISemantic E(PostfixExpression_Index x, ISemantic foreExpression)
        {
            if (eval)
            {
                //TODO: Access pointer arrays(?)

                if (foreExpression is ArrayValue)                 // ArrayValue must be checked first due to inheritance!
                {
                    var av = foreExpression as ArrayValue;

                    // Make $ operand available
                    var arrLen_Backup = ValueProvider.CurrentArrayLength;
                    ValueProvider.CurrentArrayLength = av.Elements.Length;

                    var n = E(x.Arguments[0]) as PrimitiveValue;

                    ValueProvider.CurrentArrayLength = arrLen_Backup;

                    if (n == null)
                    {
                        EvalError(x.Arguments[0], "Returned no value");
                        return(null);
                    }

                    int i = 0;
                    try{
                        i = Convert.ToInt32(n.Value);
                    }
                    catch
                    {
                        EvalError(x.Arguments[0], "Index expression must be of type int");
                        return(null);
                    }

                    if (i < 0 || i > av.Elements.Length)
                    {
                        EvalError(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                        return(null);
                    }

                    return(av.Elements[i]);
                }
                else if (foreExpression is AssociativeArrayValue)
                {
                    var aa = (AssociativeArrayValue)foreExpression;

                    var key = E(x.Arguments[0]);

                    if (key == null)
                    {
                        EvalError(x.Arguments[0], "Returned no value");
                        return(null);
                    }

                    ISymbolValue val = null;

                    foreach (var kv in aa.Elements)
                    {
                        if (kv.Key.Equals(key))
                        {
                            return(kv.Value);
                        }
                    }

                    EvalError(x, "Could not find key '" + val + "'");
                    return(null);
                }

                EvalError(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);

                return(null);
            }
            else
            {
                foreExpression = DResolver.StripMemberSymbols(AbstractType.Get(foreExpression));

                if (foreExpression is AssocArrayType)
                {
                    var ar = foreExpression as AssocArrayType;

                    /*
                     * myType_Array[0] -- returns TypeResult myType
                     * return the value type of a given array result
                     */
                    //TODO: Handle opIndex overloads

                    return(new ArrayAccessSymbol(x, ar.ValueType));
                }

                /*
                 * int* a = new int[10];
                 *
                 * a[0] = 12;
                 */
                else if (foreExpression is PointerType)
                {
                    return((foreExpression as PointerType).Base);
                }
                //return new ArrayAccessSymbol(x,((PointerType)foreExpression).Base);

                else if (foreExpression is DTuple)
                {
                    var tt = foreExpression as DTuple;

                    if (x.Arguments != null && x.Arguments.Length != 0)
                    {
                        var idx = EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue;

                        if (idx == null || !DTokens.BasicTypes_Integral[idx.BaseTypeToken])
                        {
                            ctxt.LogError(x.Arguments[0], "Index expression must evaluate to integer value");
                        }
                        else if (idx.Value > (decimal)Int32.MaxValue ||
                                 (int)idx.Value >= tt.Items.Length ||
                                 (int)idx.Value < 0)
                        {
                            ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length);
                        }
                        else
                        {
                            return(tt.Items[(int)idx.Value]);
                        }
                    }
                }

                ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            }

            return(null);
        }

        ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);                // Still of the array's type.
            }
            if (!(foreExpression is ArrayValue))
            {
                EvalError(x.PostfixForeExpression, "Must be an array");
                return(null);
            }

            var ar = (ArrayValue)foreExpression;
            var sl = (PostfixExpression_Slice)x;

            // If the [ ] form is used, the slice is of the entire array.
            if (sl.FromExpression == null && sl.ToExpression == null)
            {
                return(foreExpression);
            }

            // Make $ operand available
            var arrLen_Backup = ValueProvider.CurrentArrayLength;

            ValueProvider.CurrentArrayLength = ar.Elements.Length;

            var bound_lower = E(sl.FromExpression) as PrimitiveValue;
            var bound_upper = E(sl.ToExpression) as PrimitiveValue;

            ValueProvider.CurrentArrayLength = arrLen_Backup;

            if (bound_lower == null || bound_upper == null)
            {
                EvalError(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type");
                return(null);
            }

            int lower = -1, upper = -1;

            try
            {
                lower = Convert.ToInt32(bound_lower.Value);
                upper = Convert.ToInt32(bound_upper.Value);
            }
            catch { EvalError(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type");
                    return(null); }

            if (lower < 0)
            {
                EvalError(sl.FromExpression, "Lower boundary must be greater than 0"); return(null);
            }
            if (lower >= ar.Elements.Length)
            {
                EvalError(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length); return(null);
            }
            if (upper < lower)
            {
                EvalError(sl.ToExpression, "Upper boundary must be greater than " + lower); return(null);
            }
            if (upper >= ar.Elements.Length)
            {
                EvalError(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length); return(null);
            }


            var rawArraySlice = new ISymbolValue[upper - lower];
            int j             = 0;

            for (int i = lower; i < upper; i++)
            {
                rawArraySlice[j++] = ar.Elements[i];
            }

            return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice));
        }

        ISemantic E(PostfixExpression_Increment x, ISemantic foreExpression)
        {
            // myInt++ is still of type 'int'
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                EvalError(new NoConstException(x));
            }
            // Must be implemented anyway regarding ctfe
            return(null);
        }

        ISemantic E(PostfixExpression_Decrement x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                EvalError(new NoConstException(x));
            }
            // Must be implemented anyway regarding ctfe
            return(null);
        }
    }
}
Example #36
0
        public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
        {
            keyVal           = null;
            fixedArrayLength = -1;
            AbstractType keyType = null;

            if (ad.KeyExpression != null)
            {
                //TODO: Template instance expressions?
                var id_x = ad.KeyExpression as IdentifierExpression;
                if (id_x != null && id_x.IsIdentifier)
                {
                    var id = new IdentifierDeclaration((string)id_x.Value)
                    {
                        Location    = id_x.Location,
                        EndLocation = id_x.EndLocation
                    };

                    keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

                    if (keyType != null)
                    {
                        var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

                        if (tt == null ||
                            !(tt.Definition is DVariable) ||
                            ((DVariable)tt.Definition).Initializer == null)
                        {
                            return(keyType);
                        }
                    }
                }

                try
                {
                    keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

                    if (keyVal != null)
                    {
                        // Take the value's type as array key type
                        keyType = keyVal.RepresentedType;

                        // It should be mostly a number only that points out how large the final array should be
                        var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
                        if (pv != null)
                        {
                            fixedArrayLength = System.Convert.ToInt32(pv.Value);

                            if (fixedArrayLength < 0)
                            {
                                ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
                            }
                        }
                        //TODO Is there any other type of value allowed?
                    }
                }
                catch { }
            }
            else
            {
                var t = Resolve(ad.KeyType, ctxt);
                ctxt.CheckForSingleResult(t, ad.KeyType);

                if (t != null && t.Length != 0)
                {
                    return(t[0]);
                }
            }

            return(keyType);
        }
        public ISymbolValue Visit(AssignExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);
            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);

            //TODO

            this.rValue = null;

            return null;
        }
Example #38
0
 public bool Equals(ISymbolValue other)
 {
     return(false);
 }
Example #39
0
 public TemplateParameterSymbol(TemplateParameter tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null)
     : base(tpn != null ? tpn.Representation : null, AbstractType.Get(typeOrValue), paramIdentifier)
 {
     this.Parameter      = tpn;
     this.ParameterValue = typeOrValue as ISymbolValue;
 }
        public ISymbolValue Visit(PostfixExpression_Slice x)
        {
            var foreExpression = EvalForeExpression(x);

            if (!(foreExpression is ArrayValue))
            {
                EvalError(x.PostfixForeExpression, "Must be an array");
                return(null);
            }

            var ar = (ArrayValue)foreExpression;
            var sl = (PostfixExpression_Slice)x;

            // If the [ ] form is used, the slice is of the entire array.
            if (sl.FromExpression == null && sl.ToExpression == null)
            {
                return(foreExpression);
            }

            // Make $ operand available
            var arrLen_Backup = ValueProvider.CurrentArrayLength;
            var len           = ar.Length;

            ValueProvider.CurrentArrayLength = len;

            var bound_lower = sl.FromExpression != null?sl.FromExpression.Accept(this) as PrimitiveValue : null;

            var bound_upper = sl.ToExpression != null?sl.ToExpression.Accept(this) as PrimitiveValue : null;

            ValueProvider.CurrentArrayLength = arrLen_Backup;

            if (bound_lower == null || bound_upper == null)
            {
                EvalError(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type");
                return(null);
            }

            int lower = -1, upper = -1;

            try
            {
                lower = Convert.ToInt32(bound_lower.Value);
                upper = Convert.ToInt32(bound_upper.Value);
            }
            catch
            {
                EvalError(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type");
                return(null);
            }

            if (lower < 0)
            {
                EvalError(sl.FromExpression, "Lower boundary must be greater than 0"); return(new NullValue(ar.RepresentedType));
            }
            if (lower >= len && len > 0)
            {
                EvalError(sl.FromExpression, "Lower boundary must be smaller than " + len); return(new NullValue(ar.RepresentedType));
            }
            if (upper < lower)
            {
                EvalError(sl.ToExpression, "Upper boundary must be greater than " + lower); return(new NullValue(ar.RepresentedType));
            }
            else if (upper > len)
            {
                EvalError(sl.ToExpression, "Upper boundary must be smaller than " + len); return(new NullValue(ar.RepresentedType));
            }

            if (ar.IsString)
            {
                return(new ArrayValue(ar.RepresentedType as ArrayType, ar.StringValue.Substring(lower, upper - lower)));
            }

            var rawArraySlice = new ISymbolValue[upper - lower];
            int j             = 0;

            for (int i = lower; i < upper; i++)
            {
                rawArraySlice[j++] = ar.Elements[i];
            }

            return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice));
        }
Example #41
0
 public abstract void Set(AbstractSymbolValueProvider vp, ISymbolValue value);
Example #42
0
 public bool Equals(ISymbolValue other)
 {
     throw new NotImplementedException();
 }
Example #43
0
 public AssocArrayPointer(DVariable accessedArray, AssocArrayType arrayType, ISymbolValue accessedItemKey)
     : base(new MemberSymbol(accessedArray, arrayType, null))
 {
     Key = accessedItemKey;
 }
Example #44
0
		public static bool IsFalseZeroOrNull(ISymbolValue v)
		{
			var pv = v as PrimitiveValue;
			if (pv != null)
				try
				{
					return pv.Value == 0m;
				}
				catch { }
			else
				return v is NullValue;

			return v != null;
		}
Example #45
0
 public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
 {
     vp[Variable] = value;
 }
        /// <summary>
        /// Evaluates the identifier/template instance as usual.
        /// If the id points to a variable, the initializer/dynamic value will be evaluated using its initializer.
        /// 
        /// If ImplicitlyExecute is false but value evaluation is switched on, an InternalOverloadValue-object will be returned
        /// that keeps all overloads passed via 'overloads'
        /// </summary>
        ISemantic TryDoCTFEOrGetValueRefs(AbstractType[] overloads, IExpression idOrTemplateInstance, bool ImplicitlyExecute = true, ISymbolValue[] executionArguments=null)
        {
            if (overloads == null || overloads.Length == 0)
                throw new EvaluationException(idOrTemplateInstance, "No symbols found");

            var r = overloads[0];
            var ex = new EvaluationException(idOrTemplateInstance, "Ambiguous expression", overloads);

            if (r is MemberSymbol)
            {
                var mr = (MemberSymbol)r;

                // If we've got a function here, execute it
                if (mr.Definition is DMethod)
                {
                    if (ImplicitlyExecute)
                    {
                        if (overloads.Length > 1)
                            throw ex;
                        return FunctionEvaluation.Execute((DMethod)mr.Definition, executionArguments, ValueProvider);
                    }

                    return new InternalOverloadValue(overloads, idOrTemplateInstance);
                }
                else if (mr.Definition is DVariable)
                {
                    if (overloads.Length > 1)
                        throw ex;
                    return new VariableValue((DVariable)mr.Definition, mr.Base, idOrTemplateInstance);
                }
            }
            else if (r is UserDefinedType)
            {
                if (overloads.Length > 1)
                    throw ex;
                return new TypeValue(r, idOrTemplateInstance);
            }

            return null;
        }
        public ISymbolValue Visit(EqualExpression x)
        {
            var lValue = this.lValue ?? (x.LeftOperand != null ? x.LeftOperand.Accept(this) : null);
            var rValue = this.rValue ?? (x.RightOperand != null ? x.RightOperand.Accept(this) : null);

            this.lValue = null;
            this.rValue = null;

            var l = TryGetValue(lValue);
            var r = TryGetValue(rValue);

            var isEq = SymbolValueComparer.IsEqual(l, r);

            return new PrimitiveValue(x.OperatorToken == DTokens.Equal ? isEq : !isEq, x);
        }
Example #48
0
 public abstract void Set(AbstractSymbolValueProvider vp, ISymbolValue value);
Example #49
0
        public static bool IsFalseZeroOrNull(ISymbolValue v)
        {
            var pv = v as PrimitiveValue;
            if (pv != null)
                try
                {
                    return !Convert.ToBoolean(pv.Value);
                }
                catch { }
            else
                return v is NullValue;

            return v != null;
        }
Example #50
0
 public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
 {
     if(vp != null && vp.ev != null)
         vp.ev.EvalError(null,"Cannot assign a value to a static property.", new[]{this, value});
     //TODO: What about array.length?
 }
        public static AbstractType EvalMethodCall(AbstractType[] baseExpression, ISymbolValue baseValue, TemplateInstanceExpression tix,
                                                  ResolutionContext ctxt,
                                                  PostfixExpression_MethodCall call, out List <ISemantic> callArguments, out ISymbolValue delegateValue,
                                                  bool returnBaseTypeOnly, AbstractSymbolValueProvider ValueProvider = null)
        {
            //TODO: Refactor this crap!

            delegateValue = null;
            callArguments = null;

            var methodOverloads = new List <AbstractType>();

            #region Search possible methods, opCalls or delegates that could be called
            bool requireStaticItems = true;             //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit
            IEnumerable <AbstractType> scanResults = baseExpression;
            var nextResults = new List <AbstractType>();

            while (scanResults != null)
            {
                foreach (var b in scanResults)
                {
                    if (b is AmbiguousType)
                    {
                        nextResults.AddRange((b as AmbiguousType).Overloads);
                    }
                    else if (b is TemplateParameterSymbol)
                    {
                        nextResults.Add((b as TemplateParameterSymbol).Base);
                    }
                    else if (b is MemberSymbol)
                    {
                        var mr = (MemberSymbol)b;

                        if (mr.Definition is DMethod)
                        {
                            methodOverloads.Add(mr);
                            continue;
                        }
                        else if (mr.Definition is DVariable)
                        {
                            // If we've got a variable here, get its base type/value reference
                            if (ValueProvider != null)
                            {
                                var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue;

                                if (dgVal != null)
                                {
                                    nextResults.Add(dgVal.Definition);
                                    continue;
                                }
                                else
                                {
                                    ValueProvider.LogError(call, "Variable must be a delegate, not anything else");
                                    return(null);
                                }
                            }
                            else
                            {
                                var bt = mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt);

                                // Must be of type delegate
                                if (bt is DelegateType)
                                {
                                    var ret = HandleCallDelegateType(ValueProvider, bt as DelegateType, methodOverloads, returnBaseTypeOnly);
                                    if (ret is ISymbolValue)
                                    {
                                        delegateValue = ret as ISymbolValue;
                                        return(null);
                                    }
                                    else if (ret is AbstractType)
                                    {
                                        return(ret as AbstractType);
                                    }
                                }
                                else
                                {
                                    /*
                                     * If mr.Node is not a method, so e.g. if it's a variable
                                     * pointing to a delegate
                                     *
                                     * class Foo
                                     * {
                                     *	string opCall() {  return "asdf";  }
                                     * }
                                     *
                                     * Foo f=new Foo();
                                     * f(); -- calls opCall, opCall is not static
                                     */
                                    nextResults.Add(bt);
                                    requireStaticItems = false;
                                }
                                //TODO: Can other types work as function/are callable?
                            }
                        }
                    }
                    else if (b is DelegateType)
                    {
                        var ret = HandleCallDelegateType(ValueProvider, b as DelegateType, methodOverloads, returnBaseTypeOnly);
                        if (ret is ISymbolValue)
                        {
                            delegateValue = ret as ISymbolValue;
                            return(null);
                        }
                        else if (ret is AbstractType)
                        {
                            return(ret as AbstractType);
                        }
                    }
                    else if (b is ClassType || b is StructType)
                    {
                        var tit = (TemplateIntermediateType)b;

                        /*
                         * auto a = MyStruct(); -- opCall-Overloads can be used
                         */
                        var classDef = tit.Definition;

                        if (classDef == null)
                        {
                            continue;
                        }

                        foreach (var i in ExpressionTypeEvaluation.GetOpCalls(tit, requireStaticItems))
                        {
                            methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol);
                        }

                        /*
                         * Every struct can contain a default ctor:
                         *
                         * struct S { int a; bool b; }
                         *
                         * auto s = S(1,true); -- ok
                         * auto s2= new S(2,false); -- error, no constructor found!
                         */
                        if (b is StructType && methodOverloads.Count == 0)
                        {
                            //TODO: Deduce parameters
                            return(b);
                        }
                    }

                    /*
                     * If the overload is a template, it quite exclusively means that we'll handle a method that is the only
                     * child inside a template + that is named as the template.
                     */
                    else if (b is TemplateType)
                    {
                        methodOverloads.Add(b);
                    }
                    else if (b is PrimitiveType)                     // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                    {
                        methodOverloads.Add(b);
                    }
                }

                scanResults = nextResults.Count == 0 ? null : nextResults.ToArray();
                nextResults.Clear();
            }
            #endregion

            if (methodOverloads.Count == 0)
            {
                return(null);
            }

            // Get all arguments' types
            callArguments = new List <ISemantic>();

            if (call.Arguments != null)
            {
                if (ValueProvider != null)
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? Evaluation.EvaluateValue(arg, ValueProvider) : null);
                    }
                }
                else
                {
                    foreach (var arg in call.Arguments)
                    {
                        callArguments.Add(arg != null ? ExpressionTypeEvaluation.EvaluateType(arg, ctxt) : null);
                    }
                }
            }

            #region If explicit template type args were given, try to associate them with each overload
            if (tix != null)
            {
                var args             = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);
                var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt);
                methodOverloads.Clear();
                if (deducedOverloads != null)
                {
                    methodOverloads.AddRange(deducedOverloads);
                }
            }
            #endregion

            #region Filter by parameter-argument comparison
            var          argTypeFilteredOverloads   = new List <AbstractType>();
            bool         hasHandledUfcsResultBefore = false;
            AbstractType untemplatedMethodResult    = null;

            foreach (var ov in methodOverloads)
            {
                if (ov is MemberSymbol)
                {
                    HandleDMethodOverload(ctxt, ValueProvider != null, baseValue, callArguments, returnBaseTypeOnly, argTypeFilteredOverloads, ref hasHandledUfcsResultBefore,
                                          ov as MemberSymbol, ref untemplatedMethodResult);
                }
                else if (ov is DelegateType)
                {
                    var dg = ov as DelegateType;
                    var bt = dg.Base ?? TypeDeclarationResolver.GetMethodReturnType(dg, ctxt);

                    //TODO: Param-Arg check

                    if (returnBaseTypeOnly)
                    {
                        argTypeFilteredOverloads.Add(bt);
                    }
                    else
                    {
                        if (dg.Base == null)
                        {
                            if (dg.IsFunctionLiteral)
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters);
                            }
                            else
                            {
                                dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as DelegateDeclaration, dg.Parameters);
                            }
                        }
                        argTypeFilteredOverloads.Add(new DelegateCallSymbol(dg, call));
                    }
                }
                else if (ov is PrimitiveType)                 // dmd 2.066: Uniform Construction Syntax. creal(3) is of type creal.
                {
                    if (ValueProvider != null)
                    {
                        if (callArguments == null || callArguments.Count != 1)
                        {
                            ValueProvider.LogError(call, "Uniform construction syntax expects exactly one argument");
                        }
                        else
                        {
                            var pv = callArguments[0] as PrimitiveValue;
                            if (pv == null)
                            {
                                ValueProvider.LogError(call, "Uniform construction syntax expects one built-in scalar value as first argument");
                            }
                            else
                            {
                                delegateValue = new PrimitiveValue(pv.Value, ov as PrimitiveType, pv.ImaginaryPart);
                            }
                        }
                    }

                    argTypeFilteredOverloads.Add(ov);
                }
            }

            // Prefer untemplated methods over templated ones
            if (untemplatedMethodResult != null)
            {
                return(untemplatedMethodResult);
            }
            #endregion

            return(AmbiguousType.Get(argTypeFilteredOverloads, tix));
        }
Example #52
0
 public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
 {
     vp[Variable] = value;
 }
        public ISymbolValue Visit(PostfixExpression_Index x)
        {
            var foreExpression = EvalForeExpression(x);

            //TODO: Access pointer arrays(?)

            if (foreExpression is ArrayValue)             // ArrayValue must be checked first due to inheritance!
            {
                var av = foreExpression as ArrayValue;

                // Make $ operand available
                var arrLen_Backup = ValueProvider.CurrentArrayLength;
                ValueProvider.CurrentArrayLength = av.Elements.Length;

                var n = x.Arguments.Length > 0 && x.Arguments[0] != null ? x.Arguments[0].Accept(this) as PrimitiveValue : null;

                ValueProvider.CurrentArrayLength = arrLen_Backup;

                if (n == null)
                {
                    EvalError(x.Arguments[0], "Returned no value");
                    return(null);
                }

                int i = 0;
                try
                {
                    i = Convert.ToInt32(n.Value);
                }
                catch
                {
                    EvalError(x.Arguments[0], "Index expression must be of type int");
                    return(null);
                }

                if (i < 0 || i > av.Elements.Length)
                {
                    EvalError(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                    return(null);
                }

                return(av.Elements[i]);
            }
            else if (foreExpression is AssociativeArrayValue)
            {
                var aa = (AssociativeArrayValue)foreExpression;

                var key = x.Arguments.Length > 0 && x.Arguments[0] != null ? x.Arguments[0].Accept(this) as PrimitiveValue : null;

                if (key == null)
                {
                    EvalError(x.Arguments[0], "Returned no value");
                    return(null);
                }

                ISymbolValue val = null;

                foreach (var kv in aa.Elements)
                {
                    if (kv.Key.Equals(key))
                    {
                        return(kv.Value);
                    }
                }

                EvalError(x, "Could not find key '" + val + "'");
                return(null);
            }

            //TODO: myClassWithAliasThis[0] -- Valid!!

            EvalError(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);
            return(null);
        }
Example #54
0
 public void Visit(ReturnStatement returnStatement)
 {
     returnedValue = Evaluation.EvaluateValue(returnStatement.ReturnExpression, vp);
 }
Example #55
0
 public virtual bool Equals(ISymbolValue other)
 {
     return(SymbolValueComparer.IsEqual(this, other));
 }
Example #56
0
 public AssocArrayPointer(MemberSymbol assocArrayVariable, ISymbolValue accessedItemKey)
     : base(assocArrayVariable)
 {
     Key = accessedItemKey;
 }
Example #57
0
 public TemplateParameterSymbol(TemplateParameter tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null)
     : base(tpn != null ? tpn.Representation : null, AbstractType.Get(typeOrValue), paramIdentifier)
 {
     this.Parameter = tpn;
     this.ParameterValue = typeOrValue as ISymbolValue;
 }
Example #58
0
 public AssocArrayPointer(DVariable accessedArray, AssocArrayType arrayType, ISymbolValue accessedItemKey)
     : base(new MemberSymbol(accessedArray, arrayType,null))
 {
     Key = accessedItemKey;
 }
Example #59
0
		/// <summary>
		/// Removes all variable references by resolving them via the given value provider.
		/// Useful when only the value is of interest, not its container or other things.
		/// </summary>
		public static ISymbolValue GetVariableContents(ISymbolValue v, AbstractSymbolValueProvider vp)
		{
			while (v is VariableValue)
				v = vp[(v as VariableValue).Variable];

			return v;
		}
Example #60
0
        public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value)
        {
            var oldV = vp[Variable];

            if (oldV is AssociativeArrayValue)
            {
                if (Key != null)
                {
                    var aa = (AssociativeArrayValue)oldV;

                    int itemToReplace = -1;

                    for (int i = 0; i < aa.Elements.Count; i++)
                        if (SymbolValueComparer.IsEqual(aa.Elements[i].Key, Key))
                        {
                            itemToReplace = i;
                            break;
                        }

                    // If we haven't found a matching key, add it to the array
                    var newElements = new KeyValuePair<ISymbolValue, ISymbolValue>[aa.Elements.Count + (itemToReplace == -1 ? 1 : 0)];
                    aa.Elements.CopyTo(newElements, 0);

                    if (itemToReplace != -1)
                        newElements[itemToReplace] = new KeyValuePair<ISymbolValue, ISymbolValue>(newElements[itemToReplace].Key, value);
                    else
                        newElements[newElements.Length - 1] = new KeyValuePair<ISymbolValue, ISymbolValue>(Key, value);

                    // Finally, make a new associative array containing the new elements
                    vp[Variable] = new AssociativeArrayValue(aa.RepresentedType as AssocArrayType, newElements);
                }
                else{
                    if(vp.ev !=null) vp.ev.EvalError(null,"Key expression must not be null", Key);
                }
            }
            else{
                if(vp.ev != null) vp.ev.EvalError(null,"Type of accessed item must be an associative array", oldV);
            }
        }