bool EnsureIntegralType(IExpression x, PrimitiveValue v) { if (!DTokens.IsBasicType_Integral(v.BaseTypeToken)) { EvalError(x, "Literal must be of integral type", new[] { (ISemantic)v }); return(false); } return(true); }
static PropOwnerType GetOwnerType(ISemantic t) { if (t is TypeValue) { t = (t as TypeValue).RepresentedType; } if (t is ArrayValue || t is ArrayType) { return(PropOwnerType.Array); } else if (t is AssociativeArrayValue || t is AssocArrayType) { return(PropOwnerType.AssocArray); } else if (t is DelegateValue || t is DelegateType) { return(PropOwnerType.Delegate); } else if (t is PrimitiveValue || t is PrimitiveType) { var tk = t is PrimitiveType ? (t as PrimitiveType).TypeToken : (t as PrimitiveValue).BaseTypeToken; if (DTokens.IsBasicType_Integral(tk)) { return(PropOwnerType.Integral); } if (DTokens.IsBasicType_FloatingPoint(tk)) { return(PropOwnerType.FloatingPoint); } } else if (t is InstanceValue || t is ClassType || t is InterfaceType || t is TemplateType || t is StructType) { return(PropOwnerType.ClassLike); } else if (t is DTuple) { return(PropOwnerType.TypeTuple); } else if (t is TemplateParameterSymbol) { var tps = t as TemplateParameterSymbol; if (tps != null && (tps.Parameter is TemplateThisParameter ? (tps.Parameter as TemplateThisParameter).FollowParameter : tps.Parameter) is TemplateTupleParameter) { return(PropOwnerType.TypeTuple); } } return(PropOwnerType.None); }
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_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); }
public ISymbolValue Visit(TraitsExpression te) { switch (te.Keyword) { case "": case null: return(null); case "hasMember": bool ret = false; var optionsBackup = ctxt.ContextIndependentOptions; ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes; AbstractType t; var pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider); if (pfa != null && t != null) { ignoreErrors = true; ret = EvalPostfixAccessExpression(this, ctxt, pfa, t, false) != null; ignoreErrors = false; } ctxt.ContextIndependentOptions = optionsBackup; return(new PrimitiveValue(ret, te)); case "identifier": if (te.Arguments != null && te.Arguments.Length == 1) { return(new ArrayValue(GetStringType(), te.Arguments[0].ToString())); } break; case "getMember": pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider); if (pfa == null || t == null) { break; } var vs = EvalPostfixAccessExpression(this, ctxt, pfa, t, ValueProvider: ValueProvider); if (vs == null || vs.Length == 0) { return(null); } return(vs[0]); case "getOverloads": optionsBackup = ctxt.ContextIndependentOptions; ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes; pfa = ExpressionTypeEvaluation.prepareMemberTraitExpression(ctxt, te, out t, ValueProvider); if (pfa != null && t != null) { vs = EvalPostfixAccessExpression(this, ctxt, pfa, t); } else { vs = null; } ctxt.ContextIndependentOptions = optionsBackup; return(new TypeValue(new DTuple(te, vs))); case "getProtection": optionsBackup = ctxt.ContextIndependentOptions; ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes; var prot = "public"; if (te.Arguments == null || te.Arguments.Length != 1 || te.Arguments[0] == null) { EvalError(te, "First trait argument must be a symbol identifier"); } else { t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[0]); if (t is DSymbol) { var dn = (t as DSymbol).Definition; if (dn.ContainsAttribute(DTokens.Private)) { prot = "private"; } else if (dn.ContainsAttribute(DTokens.Protected)) { prot = "protected"; } else if (dn.ContainsAttribute(DTokens.Package)) { prot = "package"; } else if (dn.ContainsAttribute(DTokens.Export)) { prot = "export"; } } else { EvalError(te, "First argument must evaluate to an existing code symbol"); } } ctxt.ContextIndependentOptions = optionsBackup; return(new ArrayValue(GetStringType(), prot)); case "getVirtualFunctions": break; case "getVirtualMethods": break; case "parent": break; case "classInstanceSize": break; case "allMembers": break; case "derivedMembers": break; case "isSame": ret = false; if (te.Arguments == null || te.Arguments.Length < 2) { EvalError(te, "isSame requires two arguments to compare"); } else { t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[0]); if (t != null) { var t2 = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, te.Arguments[1]); if (t2 != null) { ret = Resolver.ResultComparer.IsEqual(t, t2); } } } return(new PrimitiveValue(ret, te)); case "compiles": ret = false; if (te.Arguments != null) { foreach (var arg in te.Arguments) { ret = arg == null || ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, arg) != null; if (!ret) { break; } } } return(new PrimitiveValue(ret, te)); } #region isXYZ-traits if (te.Keyword.StartsWith("is")) { var optionsBackup = ctxt.ContextIndependentOptions; ctxt.ContextIndependentOptions = ResolutionOptions.IgnoreAllProtectionAttributes; bool ret = false; if (te.Arguments != null) { foreach (var arg in te.Arguments) { var t = ExpressionTypeEvaluation.ResolveTraitArgument(ctxt, arg); bool tested = true; switch (te.Keyword) { case "isVirtualFunction": case "isVirtualMethod": var ms = t as MemberSymbol; if (ms == null || !(ms.Definition is DMethod)) { break; } var dm = ms.Definition as DMethod; var dc = dm.Parent as DClassLike; if (dc != null && dc.ClassType != DTokens.Struct) { bool includeFinalNonOverridingMethods = te.Keyword == "isVirtualFunction"; ret = !dm.ContainsAttribute(includeFinalNonOverridingMethods ? (byte)0 : DTokens.Final, DTokens.Static); } break; case "isAbstractFunction": ms = t as MemberSymbol; ret = ms != null && ms.Definition is DMethod && ms.Definition.ContainsAttribute(DTokens.Abstract); break; case "isFinalFunction": ms = t as MemberSymbol; if (ms != null && ms.Definition is DMethod) { ret = ms.Definition.ContainsAttribute(DTokens.Abstract) || (ms.Definition.Parent is DClassLike && (ms.Definition.Parent as DClassLike).ContainsAttribute(DTokens.Final)); } break; case "isStaticFunction": ms = t as MemberSymbol; ret = ms != null && ms.Definition is DMethod && ms.Definition.IsStatic; break; case "isRef": ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Ref); break; case "isOut": ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Out); break; case "isLazy": ret = t is MemberSymbol && (t as MemberSymbol).Definition.ContainsAttribute(DTokens.Lazy); break; default: tested = false; break; } t = DResolver.StripMemberSymbols(t); if (!tested) { switch (te.Keyword) { case "isArithmetic": var pt = t as PrimitiveType; ret = pt != null && ( DTokens.IsBasicType_Integral(pt.TypeToken) || DTokens.IsBasicType_FloatingPoint(pt.TypeToken)); break; case "isFloating": pt = t as PrimitiveType; ret = pt != null && DTokens.IsBasicType_FloatingPoint(pt.TypeToken); break; case "isIntegral": pt = t as PrimitiveType; ret = pt != null && DTokens.IsBasicType_Integral(pt.TypeToken); break; case "isScalar": pt = t as PrimitiveType; ret = pt != null && DTokens.IsBasicType(pt.TypeToken); break; case "isUnsigned": pt = t as PrimitiveType; ret = pt != null && DTokens.IsBasicType_Unsigned(pt.TypeToken); break; case "isAbstractClass": ret = t is ClassType && (t as ClassType).Definition.ContainsAttribute(DTokens.Abstract); break; case "isFinalClass": ret = t is ClassType && (t as ClassType).Definition.ContainsAttribute(DTokens.Final); break; case "isAssociativeArray": ret = t is AssocArrayType && !(t is ArrayType); break; case "isStaticArray": ret = t is ArrayType && (t as ArrayType).IsStaticArray; break; } } if (!ret) { break; } } } ctxt.ContextIndependentOptions = optionsBackup; return(new PrimitiveValue(ret, te)); } else { EvalError(te, "Illegal trait token"); return(null); } #endregion }