public static string EvaluateMixinExpressionContent(AbstractSymbolValueProvider vp,MixinExpression x) { var ev = new Evaluation(vp); ev.resolveConstOnly = true; var v = x.AssignExpression != null ? x.AssignExpression.Accept(ev) as ArrayValue : null; return v != null && v.IsString ? v.StringValue : null; }
public static AbstractType EvaluateType(IExpression x, ResolutionContext ctxt) { var ev = new Evaluation(ctxt); ISemantic t = null; if(!Debugger.IsAttached) try { t = ev.E(x); } catch { } else t = ev.E(x); return AbstractType.Get(t); }
public override ISymbolValue this[DVariable n] { get { if (n == null) { return(new ErrorValue(new EvaluationException("There must be a valid variable node given in order to retrieve its value"))); } if (n.IsConst) { if (varsBeingResolved.Contains(n)) { return(new ErrorValue(new EvaluationException("Cannot reference itself"))); } varsBeingResolved.Add(n); // .. resolve it's pre-compile time value and make the returned value the given argument ISymbolValue val; try{ val = Evaluation.EvaluateValue(n.Initializer, this); } finally{ varsBeingResolved.Remove(n); } // If it's null, then the initializer is null - which is equal to e.g. 0 or null !; if (val != null) { return(val); } } return(new ErrorValue(new EvaluationException(n + " must have a constant initializer"))); } set { throw new NotImplementedException(); } }
public AbstractType Visit(MixinExpression x) { var s = Evaluation.EvaluateMixinExpressionContent(ctxt, x); if (s == null) { EvalError(new InvalidStringException(x)); return(null); } // Parse it as an expression var ex = DParser.ParseAssignExpression(s); if (ex == null) { EvalError(new EvaluationException(x, "Invalid expression code given")); return(null); } //TODO: Excessive caching // Evaluate the expression's type/value return(ex.Accept(this)); }
public static AbstractType[] TryGetUnfilteredMethodOverloads(IExpression foreExpression, ResolverContextStack ctxt, IExpression supExpression = null) { if (foreExpression is TemplateInstanceExpression) { return(Evaluation.GetOverloads((TemplateInstanceExpression)foreExpression, ctxt, null)); } else if (foreExpression is IdentifierExpression) { return(Evaluation.GetOverloads((IdentifierExpression)foreExpression, ctxt)); } else if (foreExpression is PostfixExpression_Access) { bool ufcs = false; // TODO? return(Evaluation.GetAccessedOverloads((PostfixExpression_Access)foreExpression, ctxt, out ufcs, null, false)); } else if (foreExpression is TokenExpression) { return(GetResolvedConstructorOverloads((TokenExpression)foreExpression, ctxt)); } else { return new[] { Evaluation.EvaluateType(foreExpression, ctxt) } }; }
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)); }
public AbstractType Visit(PostfixExpression_Index x) { var foreExpression = EvalForeExpression(x); // myArray[0]; myArray[0..5]; // opIndex/opSlice ? if (foreExpression is MemberSymbol) { foreExpression = DResolver.StripMemberSymbols(foreExpression); } var udt = foreExpression as UserDefinedType; if (udt != null) { ctxt.CurrentContext.IntroduceTemplateParameterTypes(udt); var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(OpIndexIdHash, AmbiguousType.TryDissolve(foreExpression), ctxt, x, false); if (overloads != null && overloads.Length > 0) { var indexArgs = x.Arguments != null ? new AbstractType[x.Arguments.Length] : null; for (int i = 0; i < indexArgs.Length; i++) { if (x.Arguments[i] != null) { indexArgs[i] = x.Arguments[i].Accept(this); } } overloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(overloads, indexArgs, true, ctxt); ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt); return(TryPretendMethodExecution(AmbiguousType.Get(overloads, x), x, indexArgs)); } ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(udt); if (foreExpression is TemplateIntermediateType) { //TODO: Proper resolution of alias this declarations var tit = foreExpression as TemplateIntermediateType; var ch = tit.Definition[DVariable.AliasThisIdentifierHash]; if (ch != null) { foreach (DVariable aliasThis in ch) { foreExpression = TypeDeclarationResolver.HandleNodeMatch(aliasThis, ctxt, foreExpression); if (foreExpression != null) { break; // HACK: Just omit other alias this' to have a quick run-through } } } if (foreExpression == null) { return(tit); } } } foreExpression = DResolver.StripMemberSymbols(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 if (ar.ValueType != null) { ar.ValueType.NonStaticAccess = true; } return(new ArrayAccessSymbol(x, ar.ValueType)); } /* * int* a = new int[10]; * * a[0] = 12; */ else if (foreExpression is PointerType) { var b = (foreExpression as PointerType).Base; if (b != null) { b.NonStaticAccess = true; } return(b); } //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 = Evaluation.EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue; if (tt.Items == null) { ctxt.LogError(tt.DeclarationOrExpressionBase, "No items in Type tuple"); } else if (idx == null || !DTokens.IsBasicType_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 || idx.Value < 0m) { ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length); } else { return(AbstractType.Get(tt.Items[(int)idx.Value])); } } } ctxt.LogError(x, "No matching base type for indexing operation"); return(null); }
public AbstractType Visit(PostfixExpression_Access ex) { return(TryPretendMethodExecution(AmbiguousType.Get(Evaluation.EvalPostfixAccessExpression(this, ctxt, ex)))); }
public static AbstractType[] GetAccessedOverloads(PostfixExpression_Access acc, ResolutionContext ctxt, ISemantic resultBase = null, bool DeducePostfixTemplateParams = true) { return(Evaluation.EvalPostfixAccessExpression <AbstractType>(new ExpressionTypeEvaluation(ctxt), ctxt, acc, resultBase, DeducePostfixTemplateParams)); }
ArrayType GetStringType(LiteralSubformat fmt = LiteralSubformat.Utf8) { return(Evaluation.GetStringType(ctxt, fmt)); }
public AbstractType Visit(TraitsExpression te) { PostfixExpression_Access pfa; AbstractType t; ResolutionOptions optionsBackup; switch (te.Keyword) { case "": case null: return(null); case "identifier": return(GetStringType()); case "getMember": pfa = prepareMemberTraitExpression(te, out t); if (pfa == null || t == null) { break; } var vs = Evaluation.EvalPostfixAccessExpression(this, ctxt, pfa, t); if (vs == null || vs.Length == 0) { return(null); } return(vs[0]); case "getOverloads": optionsBackup = ctxt.ContextIndependentOptions; ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes; pfa = prepareMemberTraitExpression(te, out t); if (pfa != null && t != null) { vs = Evaluation.EvalPostfixAccessExpression(this, ctxt, pfa, t); } else { vs = null; } ctxt.ContextIndependentOptions = optionsBackup; return(new DTuple(te, vs)); case "getProtection": return(GetStringType()); case "getVirtualFunctions": break; case "getVirtualMethods": break; case "parent": break; case "classInstanceSize": break; case "allMembers": break; case "derivedMembers": break; case "compiles": return(new PrimitiveType(DTokens.Bool)); } if (te.Keyword.StartsWith("is") || te.Keyword.StartsWith("has")) { return(new PrimitiveType(DTokens.Bool)); } return(null); }
public AbstractType Visit(ImportExpression x) { return(Evaluation.GetStringType(ctxt)); }
/// <summary> /// Since most expressions should return a single type only, it's not needed to use this function unless you might /// want to pay attention on (illegal) multiple overloads. /// </summary> public static AbstractType[] EvaluateTypes(IExpression x, ResolutionContext ctxt) { var ev = new Evaluation(ctxt); ISemantic t = null; if(!Debugger.IsAttached) try { t = ev.E(x); } catch { } else t = ev.E(x); if (t is InternalOverloadValue) return ((InternalOverloadValue)t).Overloads; return t == null ? null : new[]{ AbstractType.Get(t) }; }
public static ISymbolValue EvaluateValue(IExpression x, AbstractSymbolValueProvider vp) { if (vp == null) vp = new StandardValueProvider(null); var ev = new Evaluation(vp); var v = ev.E(x) as ISymbolValue; if(v == null && ev.Errors.Count != 0) return new ErrorValue(ev.Errors.ToArray()); return v; }
public AbstractType Visit(PostfixExpression_Index x) { var foreExpression = EvalForeExpression(x); // myArray[0]; myArray[0..5]; // opIndex/opSlice ? if (foreExpression is MemberSymbol) { foreExpression = DResolver.StripMemberSymbols(foreExpression); } foreExpression = DResolver.StripMemberSymbols(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 = Evaluation.EvaluateValue(x.Arguments[0], ctxt) as PrimitiveValue; if (tt.Items == null) { ctxt.LogError(tt.DeclarationOrExpressionBase, "No items in Type tuple"); } else if (idx == null || !DTokens.IsBasicType_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 || idx.Value < 0m) { ctxt.LogError(x.Arguments[0], "Index number must be a value between 0 and " + tt.Items.Length); } else { return(AbstractType.Get(tt.Items[(int)idx.Value])); } } } ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression")); return(null); }