public override void VisitAddressDereference(AddressDereference dereference) { if (dereference?.Address is UnaryExpression expression) { if ((expression.Type as Reference)?.ConstructorName.Name.Contains("Guid@") == true) { AddProblem(expression); } } base.VisitAddressDereference(dereference); }
public override Expression VisitAddressDereference(AddressDereference addr) { if (this._string == null) { this._string = new StringBuilder(); } this._string.Append("::$Deref{"); Expression e = base.VisitAddressDereference(addr); this._string.Append("}"); return(e); }
public static string GetVariableName(Expression expression) { ArgumentUtility.CheckNotNull("expression", expression); string variableName = null; if (expression is Parameter) { Parameter operand = (Parameter)expression; variableName = operand.Name.Name; } else if (expression is Local) { Local operand = (Local)expression; variableName = operand.Name.Name; } else if (expression.NodeType == NodeType.AddressOf) { Local operand = ((UnaryExpression)expression).Operand as Local; if (operand != null) { variableName = operand.Name.Name; } } else if (expression.NodeType == NodeType.AddressDereference) { AddressDereference addressDereference = (AddressDereference)expression; variableName = GetVariableName(addressDereference.Address); } else if (expression is MemberBinding) { MemberBinding memberBinding = (MemberBinding)expression; if (memberBinding.BoundMember is Field) { Field field = (Field)memberBinding.BoundMember; variableName = field.Name.Name; } } else if (expression.NodeType == NodeType.Indexer) { Indexer indexer = (Indexer)expression; variableName = GetVariableName(indexer.Object); } return(variableName); }
public override Expression VisitAddressDereference(AddressDereference addr){ if (addr == null) return null; bool unboxDeref = addr.Address != null && addr.Address.NodeType == NodeType.Unbox; addr.Address = this.VisitExpression(addr.Address); if (addr.Address == null) return null; if (unboxDeref && addr.Address.NodeType != NodeType.Unbox) return addr.Address; Reference reference = addr.Address.Type as Reference; if (reference != null) addr.Type = reference.ElementType; return addr; }
public override Expression VisitMethodCall(MethodCall call) { if (call == null) return null; NameBinding nb = call.Callee as NameBinding; if (nb != null) { if (nb.Identifier != Looker.NotFound) { this.VisitNameBinding(nb); //Reports the error return null; } int numPars = call.Operands == null ? 0 : call.Operands.Count; bool callOperandsAlreadyNull = (call.Operands == null); ExpressionList operands = call.Operands = this.VisitExpressionList(call.Operands); if (operands == null && !callOperandsAlreadyNull || operands != null && operands.Count != numPars) return null; for (int i = 0; i < numPars; i++) if (call.Operands[i] == null) return null; //The error could have been caused by the bad argument. bool hasArglist = false; int arglistIndex = -1; for (int i = 0; i < numPars; i++) { if (call.Operands[i] is ArglistArgumentExpression) { hasArglist = true; arglistIndex = i; break; } } MemberList members = nb.BoundMembers; int n = members == null ? 0 : members.Count; MethodList ambiguousMethods = new MethodList(n); Method inaccessibleMethod = null; Method templateMethodWithFailedInference = null; Method objectMatchArglistMethod = null; for (int i = 0; i < n; i++) { Method meth = members[i] as Method; if (meth == null) continue; if ((meth.Parameters == null ? 0 : meth.Parameters.Count) != numPars) continue; if (this.NotAccessible(meth)) { inaccessibleMethod = meth; continue; } else { string mname = meth.Name != null ? meth.Name.ToString() : ""; if (this.insideMethodContract || this.insideInvariant) { if (!this.AsAccessible(meth, currentMethod) && !this.insideInvariant) { this.HandleError(meth, Error.MemberNotVisible, this.GetTypeName(meth.DeclaringType)+"."+mname); // WS better error message return null; } if ((this.insideMethodContract || this.insideAssertOrAssume) && !this.IsTransparentForMethodContract(meth, currentMethod)) { this.HandleError(meth, Error.MemberMustBePureForMethodContract, this.GetTypeName(meth.DeclaringType)+"."+mname); return null; } if (this.insideInvariant && !this.IsTransparentForInvariant(meth, currentMethod)) { this.HandleError(meth, Error.MemberMustBePureForInvariant, this.GetTypeName(meth.DeclaringType)+"."+mname); return null; } } else if (!this.IsModelUseOk(meth, currentMethod)) { this.HandleError(meth, Error.ModelMemberUseNotAllowedInContext, this.GetTypeName(meth.DeclaringType)+"."+mname); return null; } } if (meth.TemplateParameters != null && meth.TemplateParameters.Count > 0) { templateMethodWithFailedInference = meth; continue; } if (hasArglist && arglistIndex < meth.Parameters.Count && meth.Parameters[arglistIndex].Type == SystemTypes.Object) { objectMatchArglistMethod = meth; } ambiguousMethods.Add(meth); } if (ambiguousMethods.Count >= 2) { this.HandleError(call, Error.AmbiguousCall, this.GetMethodSignature(ambiguousMethods[0]), this.GetMethodSignature(ambiguousMethods[1])); return null; } if (inaccessibleMethod != null) { this.HandleError(call, Error.MemberNotVisible, this.GetMethodSignature(inaccessibleMethod)); return null; } if (templateMethodWithFailedInference != null) { this.HandleError(call, Error.CannotInferMethTypeArgs, this.GetMethodSignature(templateMethodWithFailedInference)); return null; } if (objectMatchArglistMethod != null) { this.HandleError(call, Error.CannotMatchArglist, objectMatchArglistMethod.Name.Name); this.HandleRelatedError(objectMatchArglistMethod); return null; } Identifier id = null; for (int i = 0; i < n; i++) { Member mem = members[i]; if (!(mem is Method)) continue; if (id == null && mem.Name != null) { id = mem.Name; string name = id.Name; if (mem is InstanceInitializer && mem.DeclaringType != null && mem.DeclaringType.Name != null) name = mem.DeclaringType.Name.Name; else if (mem.IsSpecialName) name = this.GetMemberName(mem); this.HandleError(nb, Error.NoOverloadWithMatchingArgumentCount, name, (call.Operands == null ? 0 : call.Operands.Count).ToString()); } this.HandleRelatedError(mem); } return null; } MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { Expression e = this.VisitExpression(call.Callee); if (e != null) { if (e is Literal && e.Type == SystemTypes.Type) this.HandleError(e, Error.TypeInBadContext, this.GetTypeName((TypeNode)((Literal)e).Value)); else { TemplateInstance templInst = e as TemplateInstance; if (templInst != null) { if (templInst.Expression == null || templInst.TypeArguments == null) return null; this.VisitExpression(templInst.Expression); return null; } //HS D if (call.Callee is Hole) return null; this.HandleError(e, Error.NoSuchMethod); } } return null; } Method method = mb.BoundMember as Method; if (method == null) { if (mb.BoundMember != null) { if (mb.BoundMember is Event) this.HandleError(mb, Error.BadCallToEventHandler, this.GetMemberSignature(mb.BoundMember)); else this.HandleNonMethodWhereMethodExpectedError(mb, mb.BoundMember); } return null; } bool initialMayReferenceThisAndBase = this.MayReferenceThisAndBase; if (mb.TargetObject is ImplicitThis || mb.TargetObject is This || mb.TargetObject is Base) { if (method is InstanceInitializer) { this.MayReferenceThisAndBase = true; //Base class constructor has been called } else if ((this.currentMethod == null && !this.insideModelfield // this is true when it is visited as part of a field initializer || !this.MayReferenceThisAndBase) // this is true when it is visited as part of a ctor with an explicit call to base in the body && !this.AllowThisTarget(method) && !this.insideInvariant) { if (mb.TargetObject is ImplicitThis) { this.HandleError(mb, Error.ObjectRequired, this.GetMethodSignature(method, true)); } else if (mb.TargetObject is Base) { this.HandleError(mb.TargetObject, Error.BaseInBadContext); } else { this.HandleError(mb.TargetObject, Error.ThisInBadContext); } return null; } } if (method == Resolver.IndexerNotFound) { if (mb.TargetObject == null) return null; if (this.TypeInVariableContext(mb.TargetObject as Literal)) return null; Expression tgtObj = this.VisitExpression(mb.TargetObject); if (tgtObj == null) return null; this.HandleError(tgtObj, Error.NotIndexable, this.GetTypeName(mb.TargetObject.Type)); return null; } if (method.Name == Looker.NotFound) { //TODO: report the error return null; } TypeNode obType = mb.TargetObject == null ? null : mb.TargetObject.Type; if (mb.TargetObject is Base) obType = this.currentType; obType = TypeNode.StripModifiers(obType); if (this.NotAccessible(method, ref obType)) { if (method.IsSpecialName && method.Parameters != null && method.Parameters.Count > 0 && method.Name.ToString().StartsWith("get_")) this.HandleError(call, Error.NotIndexable, this.GetTypeName(mb.TargetObject.Type)); else if (mb.TargetObject == null || mb.TargetObject.Type == null || this.NotAccessible(method)) this.HandleError(call, Error.MemberNotVisible, this.GetMethodSignature(method)); else this.HandleError(mb.BoundMemberExpression == null ? mb : mb.BoundMemberExpression, Error.NotVisibleViaBaseType, this.GetMethodSignature(method), this.GetTypeName(mb.TargetObject.Type), this.GetTypeName(this.currentType)); return null; } else { if (this.insideMethodContract || this.insideInvariant || this.insideAssertOrAssume) { string mname = method.Name == null ? "" : method.Name.ToString(); if (!this.AsAccessible(method, currentMethod) && !this.insideInvariant && !this.insideMethodContract && !this.insideAssertOrAssume) { this.HandleError(mb, Error.MemberNotVisible, this.GetTypeName(method.DeclaringType)+"."+mname); return null; } if ((this.insideMethodContract || this.insideAssertOrAssume) && !this.IsTransparentForMethodContract(method, currentMethod)) { this.HandleError(mb, Error.MemberMustBePureForMethodContract, this.GetTypeName(method.DeclaringType)+"."+mname); return null; } if (this.insideInvariant && !this.IsTransparentForInvariant(method, currentMethod)) { this.HandleError(mb, Error.MemberMustBePureForInvariant, this.GetTypeName(method.DeclaringType)+"."+mname); return null; } } else if (!this.IsModelUseOk(method, currentMethod)) { string mname = method.Name == null ? "" : method.Name.ToString(); this.HandleError(mb, Error.ModelMemberUseNotAllowedInContext, this.GetTypeName(method.DeclaringType)+"."+mname); return null; } } this.CheckDirectCallOfFinalize(method, call); if (method == this.currentMethod && method is InstanceInitializer) { this.HandleError(call, Error.RecursiveConstructorCall, this.GetMethodSignature(method)); return null; } if (method.IsStatic) { Expression targetOb = mb.TargetObject; if (targetOb != null) { MemberBinding memb = targetOb as MemberBinding; if (memb == null || memb.BoundMember == null || memb.Type == null || memb.Type.Name == null || memb.BoundMember.Name.UniqueIdKey != memb.Type.Name.UniqueIdKey) { MethodCall mcall = targetOb as MethodCall; memb = mcall == null ? null : mcall.Callee as MemberBinding; TypeNode mcallType = mcall == null ? null : TypeNode.StripModifiers(mcall.Type); if (memb == null || memb.BoundMember == null || !memb.BoundMember.IsSpecialName || mcallType == null || mcallType.Name == null || memb.BoundMember.Name.ToString() != "get_"+mcallType.Name.ToString()) { targetOb = this.VisitExpression(targetOb); if (targetOb != null) this.HandleError(targetOb, Error.TypeNameRequired, this.GetMethodSignature(method)); } } mb.TargetObject = targetOb = null; } } else { bool targetObIsNonNull = false; bool outerMayReferenceThisAndBase = this.MayReferenceThisAndBase; if (this.AllowThisTarget(method)) this.MayReferenceThisAndBase = true; Expression targetOb = mb.TargetObject = this.VisitExpression(mb.TargetObject); this.MayReferenceThisAndBase = outerMayReferenceThisAndBase; if (targetOb != null) targetObIsNonNull = this.typeSystem.IsNonNullType(targetOb.Type); if (targetOb is Literal && targetOb.Type == SystemTypes.Type) { this.HandleError(mb, Error.ObjectRequired, this.GetMethodSignature(method, true)); return null; } if (this.currentMethod != null && this.currentMethod.IsStatic) { if (targetOb is ImplicitThis || targetOb is This || targetOb is Base) { ImplicitThis ithis = targetOb as ImplicitThis; if (ithis != null) { bool callToNestedFunction = false; if (this.currentMethod.Scope.CapturedForClosure) { TypeNode t = this.currentMethod.Scope.ClosureClass; while (t != null && !callToNestedFunction) { callToNestedFunction = t == method.DeclaringType; t = t.BaseType; } } if (!callToNestedFunction) ithis = null; } if (ithis == null) { this.HandleError(mb, Error.ObjectRequired, this.GetMethodSignature(method)); return null; } targetOb = new CurrentClosure(this.currentMethod, this.currentMethod.DeclaringType); } } TypeNode tObType = method.DeclaringType; if (tObType == null) return null; if (tObType.TemplateParameters != null && tObType.Template == null) tObType = tObType.GetTemplateInstance(tObType, tObType.TemplateParameters); if ((method.CallingConvention & CallingConventionFlags.ExplicitThis) != 0) { if (method.Parameters == null || method.Parameters.Count < 1 || method.Parameters[0] == null) Debug.Assert(false); else tObType = method.Parameters[0].Type; } if (tObType != null) { if (targetOb == null) return null; if (tObType.IsValueType) { targetOb = this.ConvertValueTypeCallTarget(targetOb, method, tObType); if (targetOb == null) return null; mb.TargetObject = this.GetAddressOf(targetOb, tObType); } else if (targetOb is Base && this.currentType != null && this.currentType.IsValueType) { targetOb = new AddressDereference(targetOb, this.currentType); mb.TargetObject = new BinaryExpression(targetOb, new MemberBinding(null, this.currentType), NodeType.Box, tObType); } else { if (tObType != targetOb.Type && !(targetOb is CurrentClosure && tObType is ClosureClass) && !(targetOb is This || targetOb is ImplicitThis)) { if (this.useGenerics && targetOb.Type is ITypeParameter && method.IsVirtual) { call.Constraint = targetOb.Type; if (targetOb.NodeType == NodeType.Indexer) targetOb = mb.TargetObject = new UnaryExpression(targetOb, NodeType.ReadOnlyAddressOf, targetOb.Type.GetReferenceType()); else targetOb = mb.TargetObject = this.GetAddressOf(targetOb, targetOb.Type); } else { Reference refType = targetOb.Type as Reference; if (this.useGenerics && refType != null && refType.ElementType is ITypeParameter) call.Constraint = refType.ElementType; else targetOb = mb.TargetObject = this.typeSystem.ExplicitCoercion(targetOb, tObType, this.TypeViewer); } if (targetOb == null) return null; } else if (targetOb.Type != null && !this.GetTypeView(targetOb.Type).IsAssignableTo(tObType) && targetOb.Type.IsNestedIn(tObType)) { this.HandleError(mb, Error.AccessToNonStaticOuterMember, this.GetTypeName(tObType), this.GetTypeName(targetOb.Type)); return null; } } } } bool savedMayReferenceThisAndBase = this.MayReferenceThisAndBase; this.MayReferenceThisAndBase = initialMayReferenceThisAndBase; this.CoerceArguments(method.Parameters, ref call.Operands, this.DoNotVisitArguments(method), method.CallingConvention); this.MayReferenceThisAndBase = savedMayReferenceThisAndBase; this.CheckForObsolesence(call, method); if (call.GiveErrorIfSpecialNameMethod && method.IsSpecialName) { string mname = method.Name == null ? null : method.Name.Name; if (mname != null && (mname.StartsWith(".") || mname.StartsWith("get_") || mname.StartsWith("set_") || mname.StartsWith("add_") || mname.StartsWith("remove_"))) this.HandleError(call, Error.CannotCallSpecialMethod, this.GetMethodSignature(method)); } if (method.IsAbstract && call.NodeType != NodeType.Callvirt) { Debug.Assert(mb.TargetObject is Base); this.HandleError(call, Error.AbstractBaseCall, this.GetMethodSignature(method)); } if (mb != null) { if (method != null && method.Contract != null && method.Contract.Ensures != null) { // Look at any checked exceptions listed in m's contract and make sure they // are covered by the list of allowedExceptions for (int i = 0, n = method.Contract.Ensures.Count; i < n; i++) { EnsuresExceptional ee = method.Contract.Ensures[i] as EnsuresExceptional; if (ee == null) continue; TypeNode thrownType = ee.Type; if (thrownType == null) continue; if (!this.GetTypeView(thrownType).IsAssignableTo(SystemTypes.ICheckedException)) continue; int j = 0; int p = this.allowedExceptions.Count; while (j < p) { TypeNode t = this.allowedExceptions[j]; if (this.GetTypeView(thrownType).IsAssignableTo(t)) break; j++; } if (j == p) { // no allowed exception covers this one this.HandleError(call, Error.CheckedExceptionNotInThrowsClause, this.GetTypeName(thrownType), this.GetMethodSignature(this.currentMethod)); } } } } int numTemplArgs = method.TemplateArguments == null ? 0 : method.TemplateArguments.Count; if (method != null && numTemplArgs > 0) { // check instantiation constraints int len = method.Template.TemplateParameters == null ? 0 : method.Template.TemplateParameters.Count; if (numTemplArgs != len) { this.HandleError(call, Error.TemplateTypeRequiresArgs, this.GetMethodSignature(method.Template), len.ToString(), "method"); return call; } Specializer specializer = len == 0 ? null : new Specializer(method.DeclaringType.DeclaringModule, method.Template.TemplateParameters, method.TemplateArguments); if (specializer != null) specializer.CurrentType = this.currentType; for (int i=0; i < len; i++) { TypeNode formal = method.Template.TemplateParameters[i]; ITypeParameter formaltp = (ITypeParameter)formal; TypeNode actual = method.TemplateArguments[i]; if (formal == null || actual == null) continue; // make sure actual is assignable to base of formal and to each interface TypeNode fbaseType = specializer == null ? formal.BaseType : specializer.VisitTypeReference(formal.BaseType); if (fbaseType != null && ( ((formaltp.TypeParameterFlags & TypeParameterFlags.ReferenceTypeConstraint) == TypeParameterFlags.ReferenceTypeConstraint && !actual.IsObjectReferenceType) || ((formaltp.TypeParameterFlags & TypeParameterFlags.ValueTypeConstraint) == TypeParameterFlags.ValueTypeConstraint && !actual.IsValueType) || !this.typeSystem.AssignmentCompatible(TypeNode.StripModifiers(actual), fbaseType, this.TypeViewer))) { Node offNode = call.CalleeExpression is TemplateInstance ? (Node)((TemplateInstance)call.CalleeExpression).TypeArgumentExpressions[i] : (Node)call.CalleeExpression; this.HandleError(offNode, Error.TypeParameterNotCompatibleWithConstraint, this.GetTypeName(actual), this.GetTypeName(fbaseType), this.GetTypeName(formal), this.GetMethodSignature(method.Template)); return call; } InterfaceList formal_ifaces = this.GetTypeView(formal).Interfaces; if (formal_ifaces != null) { for (int j = 0, n = formal_ifaces.Count; j < n; j++) { TypeNode intf = specializer == null ? formal_ifaces[j] : specializer.VisitTypeReference(formal_ifaces[j]); intf = TypeNode.StripModifiers(intf); if (intf == null) continue; if (intf != SystemTypes.ITemplateParameter && !this.typeSystem.AssignmentCompatible(TypeNode.StripModifiers(actual), intf, this.TypeViewer)) { Node offNode = call.CalleeExpression is TemplateInstance ? (Node)((TemplateInstance)call.CalleeExpression).TypeArgumentExpressions[i] : (Node)call.CalleeExpression; this.HandleError(offNode, Error.TypeParameterNotCompatibleWithConstraint, this.GetTypeName(actual), this.GetTypeName(intf), this.GetTypeName(formal), this.GetMethodSignature(method.Template)); return call; } } } } this.CheckGenericMethodSpecialConstraints(method, call); } return call; }
public override Expression VisitAddressDereference(AddressDereference addr){ if (addr == null) return null; addr.Type = SystemTypes.Object; //TODO: arrange for an error if the type is not determined below Expression aExpr = addr.Address = this.VisitExpression(addr.Address); if (aExpr != null && aExpr.Type != null){ TypeNode aExprType = TypeNode.StripModifiers(aExpr.Type); Reference refType = aExprType as Reference; if (refType != null) aExprType = TypeNode.StripModifiers(refType.ElementType); switch(aExprType.NodeType){ case NodeType.Pointer: addr.Type = ((Pointer)aExprType).ElementType; break; case NodeType.Struct: if (aExprType.Template == SystemTypes.GenericBoxed) addr.Type = this.typeSystem.GetStreamElementType(aExprType, this.TypeViewer); break; } } return addr; }
void Factor(Expression target, out Expression e) { e = null; Member m; ExpressionList es; Expression p; Expression p1; Expression p2; TypeNode t1; /*Identifier blockVarId;*/ MemberBinding mb; switch (la.kind) { case 2: case 3: case 4: case 70: case 71: case 72: case 73: case 74: case 75: { Literal(out e); break; } case 27: case 30: case 55: { Local(out p); e = p; break; } case 1: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 25: case 26: case 28: case 35: { MemberRef(out m); Debug.Assert(m != null); e = new MemberBinding(target,m); if (la.kind == 49) { ArgExprs(out es); Method meth = (Method)m; if ( ! meth.IsVirtual){ e = new MethodCall(e, es, NodeType.Call); }else{ e = new MethodCall(e, es, NodeType.Callvirt); /*dangerous*/ } e.Type = meth.ReturnType; } break; } case 54: { BlockVar(out mb); Debug.Assert(target == null); e = mb; Debug.Assert(e != null); // block variable not found break; } case 5: { Get(); Expect(38); Expect(22); Expr(out e); OldExpression oe = new OldExpression(e); oe.Type = e.Type; e = oe; Expect(24); break; } case 22: { Get(); Expr(out e); Expect(24); break; } case 39: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.ExplicitCoercion); e.Type = t1; break; } case 40: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Is); e.Type = SystemTypes.Boolean; break; } case 41: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Castclass); e.Type = t1; break; } case 42: { Get(); Expect(22); PType(out t1); Expect(24); e = new UnaryExpression(new Literal(t1, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type)); break; } case 43: { Get(); Expect(22); Expr(out p); Expect(23); Expr(out p1); Expect(23); Expr(out p2); Expect(23); PType(out t1); Expect(24); e = new TernaryExpression(p,p1,p2,NodeType.Conditional,t1); break; } case 44: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Box); e.Type = SystemTypes.Object; break; } case 45: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Unbox); e.Type = t1.GetReferenceType(); break; } case 46: { Get(); Expect(22); Expr(out p); Expect(24); e = new UnaryExpression(p, NodeType.RefAddress, p.Type); break; } case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: { Quantifier(out e); break; } case 65: { TrueComprehension(out e); break; } case 47: { Get(); if (la.kind == 48 || la.kind == 51 || la.kind == 52) { if (la.kind == 48) { Get(); Expect(22); PType(out t1); Expect(24); Expect(49); Expr(out p); Expect(50); TypeNode newType = p.Type.GetReferenceType(); e = new UnaryExpression(p,NodeType.AddressOf,newType); } else if (la.kind == 51) { Get(); Expect(49); Expr(out p); Expect(50); Reference r = (Reference) p.Type; if (r != null) e = new AddressDereference(p,r.ElementType); else e = new AddressDereference(p, SystemTypes.UInt8); } else { TypeNode tt1 = null, tt2 = null, tt3 = null; Get(); Expect(22); PType(out tt1); Expect(23); PType(out tt2); Expect(24); Expect(49); Expr(out p); Expect(23); PType(out tt3); Expect(50); e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; } } else if (la.kind == 53) { TypeNode tt1 = null, tt2 = null, tt3 = null; Get(); Expect(22); PType(out tt1); Expect(23); PType(out tt2); Expect(24); Expect(49); Expr(out p); Expect(23); PType(out tt3); Expect(50); e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; } else if (StartOf(2)) { OperatorNode(out p); e = p; } else SynErr(111); break; } default: SynErr(112); break; } }
public virtual void VisitAddressDereference(AddressDereference addr) { if (addr == null) return; this.VisitExpression(addr.Address); }
private static string addrderef2str(AddressDereference ad) { return "*" + expression2str(ad.Address, false); }
public virtual Expression VisitLiftedPostfixExpression(PostfixExpression pExpr) { if (pExpr == null) return null; if (!this.typeSystem.IsNullableType(pExpr.Type)) { Debug.Assert(false); return null; } LRExpression lrExpr = this.VisitTargetExpression(pExpr.Expression) as LRExpression; if (lrExpr == null) return null; TypeNode urType = this.typeSystem.RemoveNullableWrapper(pExpr.Type); TypeNode paramType = urType; LocalList locals = lrExpr.Temporaries; ExpressionList subs = lrExpr.SubexpressionsToEvaluateOnce; StatementList statements = new StatementList(); BlockExpression result = new BlockExpression(new Block(statements)); for (int i = 0, n = locals.Count; i < n; i++) statements.Add(new AssignmentStatement(locals[i], subs[i])); EnumNode eType = urType as EnumNode; if (eType != null) urType = eType.UnderlyingType; Local temp = new Local(Identifier.Empty, pExpr.Type); Local tempNew = new Local(Identifier.Empty, pExpr.Type); Expression e = this.typeSystem.ExplicitCoercion(lrExpr.Expression, pExpr.Type, this.TypeViewer); statements.Add(new AssignmentStatement(temp, this.VisitExpression(e))); Method hasValue = this.GetTypeView(pExpr.Type).GetMethod(StandardIds.getHasValue); Method getValueOrDefault = this.GetTypeView(pExpr.Type).GetMethod(StandardIds.GetValueOrDefault); Method ctor = this.GetTypeView(pExpr.Type).GetMethod(StandardIds.Ctor, paramType); Block pushValue = new Block(); Block done = new Block(); Expression tempHasValue = new MethodCall(new MemberBinding(new UnaryExpression(temp, NodeType.AddressOf), hasValue), null); statements.Add(new Branch(tempHasValue, pushValue)); statements.Add(new AssignmentStatement(new AddressDereference(new UnaryExpression(tempNew, NodeType.AddressOf), pExpr.Type), new Literal(null, CoreSystemTypes.Object))); statements.Add(new Branch(null, done)); statements.Add(pushValue); Expression value = new MethodCall(new MemberBinding(new UnaryExpression(temp, NodeType.AddressOf), getValueOrDefault), null); value.Type = paramType; Expression one = GetOneOfType(urType); Expression newUVal = new BinaryExpression(value, one, pExpr.Operator, urType is Pointer ? urType : one.Type); Construct cons = new Construct(new MemberBinding(null, ctor), new ExpressionList(newUVal)); result.Type = ctor.DeclaringType; statements.Add(new AssignmentStatement(tempNew, cons)); statements.Add(done); Expression target = this.VisitTargetExpression(lrExpr.Expression); MethodCall mcall = target as MethodCall; if (mcall != null) { mcall.Operands.Add(tempNew); statements.Add(new ExpressionStatement(mcall)); } else if (target != null) { if (target.Type is Reference) { Local temp2 = new Local(Identifier.Empty, pExpr.Type); statements.Add(new AssignmentStatement(temp2, tempNew)); tempNew = temp2; target = new AddressDereference(target, pExpr.Type); } statements.Add(new AssignmentStatement(target, tempNew)); } statements.Add(new ExpressionStatement(temp)); result.Type = pExpr.Type; result.SourceContext = pExpr.SourceContext; result.Block.SourceContext = pExpr.SourceContext; return result; }
public override Expression VisitPrefixExpression(PrefixExpression pExpr) { if (pExpr == null) return null; if (this.typeSystem.IsNullableType(pExpr.Type)) return VisitLiftedPrefixExpression(pExpr); StatementList statements = new StatementList(); BlockExpression result = new BlockExpression(new Block(statements)); LRExpression lrExpr = this.VisitTargetExpression(pExpr.Expression) as LRExpression; if (lrExpr == null) return null; LocalList locals = lrExpr.Temporaries; ExpressionList subs = lrExpr.SubexpressionsToEvaluateOnce; for (int i = 0, n = locals.Count; i < n; i++) statements.Add(new AssignmentStatement(locals[i], subs[i],pExpr.SourceContext)); TypeNode rType = pExpr.Type; EnumNode eType = rType as EnumNode; if (eType != null) rType = eType.UnderlyingType; Expression newVal = null; if (pExpr.OperatorOverload != null){ ExpressionList arguments = new ExpressionList(1); arguments.Add(this.VisitExpression(lrExpr.Expression)); newVal = new MethodCall(new MemberBinding(null, pExpr.OperatorOverload), arguments, NodeType.Call, rType); }else{ Expression e = this.typeSystem.AutoDereferenceCoercion(lrExpr.Expression); Expression one = GetOneOfType(rType); newVal = new BinaryExpression(this.VisitExpression(e), one, pExpr.Operator, rType is Pointer ? rType : one.Type); } Local temp = new Local(Identifier.Empty, newVal.Type); statements.Add(new AssignmentStatement(temp, newVal,pExpr.SourceContext)); Expression target = this.VisitTargetExpression(lrExpr.Expression); MethodCall mcall = target as MethodCall; if (mcall != null){ mcall.Operands.Add(temp); statements.Add(new ExpressionStatement(mcall)); }else if (target != null){ if (target.Type is Reference) { target = new AddressDereference(target, rType); } statements.Add(new AssignmentStatement(target, this.typeSystem.ExplicitCoercion(temp, target.Type, this.TypeViewer),pExpr.SourceContext)); } statements.Add(new ExpressionStatement(temp,pExpr.SourceContext)); result.Type = pExpr.Type; return result; }
public override Expression VisitOldExpression(OldExpression oldExp) { Expression/*?*/ transformedExpression = oldExp; if (this.toplevelOldExpression == null) { this.toplevelOldExpression = oldExp; this.collectSubExpsDependentOnQuantifiedVars(oldExp); transformedExpression = this.markOldSubExps(oldExp); } if (transformedExpression != oldExp) { // if we are not at the toplevel, or the transformed top level is not the old expression, // which means the old operator has been pushed down using the distribution law. Expression result = this.VisitExpression(transformedExpression); if (this.toplevelOldExpression == oldExp) { // leave top level old expression this.toplevelOldExpression = null; this.subExpsDependentOnQuantifiedVars = null; } return result; } else { OldExpression oldExpression = transformedExpression as OldExpression; //^ assert oldExpression != null; TypeNode t = oldExpression.Type; Reference rt = t as Reference; Expression e = oldExpression.expression; if (rt != null) { e = new AddressDereference(e, rt.ElementType, e.SourceContext); } string oldName = e.SourceContext.SourceText != null && e.SourceContext.SourceText.Length > 0 ? "old(" + e.SourceContext.SourceText + ")" : "$SSold" + e.UniqueKey; Local l = new Local(Identifier.For(oldName), e.Type); #region Add local to method's local list so it gets the right debug scope // Since the scope of the "old" local is the entire method body, it suffices // to add it to the method's local list. Because of how that is processed in Writer, // that means the local's scope will be the entire method body. if (this.currentMethod.LocalList == null) { this.currentMethod.LocalList = new LocalList(); } this.currentMethod.LocalList.Add(l); #endregion // normalize the old expression itself e = this.VisitExpression(e); Statement a = this.initializeOldExp(l, e, oldExpression.ShallowCopyUptoDimension); this.currentContractPrelude.Statements.Add(a); this.currentContractPrelude.HasLocals = true; if (this.toplevelOldExpression == oldExpression) { this.toplevelOldExpression = null; this.subExpsDependentOnQuantifiedVars = null; } if (rt != null) return new UnaryExpression(l, NodeType.AddressOf, t, e.SourceContext); else return l; } }
public Block CreateClosureClassInstance(Method method){ Class closureClass = method.Scope.ClosureClass; Block newBlock = new Block(); StatementList statements = new StatementList(3); newBlock.Statements = statements; newBlock.HasLocals = true; // can't set currentClosureLocal in SetUpClosureClass because in a ctor, cannot use "closure.this" // instead of "this" until after base/self ctor call is made. this.currentClosureLocal = new Local(Identifier.For("SS$Closure Class Local"+method.UniqueKey), closureClass,newBlock); statements.Add(new AssignmentStatement(this.currentClosureLocal, new Construct(new MemberBinding(null, this.GetTypeView(closureClass).GetConstructors()[0]), new ExpressionList(0)))); if (method.Scope.ThisField != null){ Expression thisValue = method.ThisParameter; if (this.currentType.IsValueType) thisValue = new AddressDereference(thisValue, this.currentType); statements.Add(new AssignmentStatement(new MemberBinding(this.currentClosureLocal, method.Scope.ThisField), thisValue)); } MemberList members = method.Scope.Members; for (int i = 0, n = members.Length; i < n; i++){ Field f = members[i] as Field; if (f != null && f.Type is Reference) continue; f.DeclaringType = closureClass; ParameterField pField = f as ParameterField; if (pField == null) continue; Parameter p = pField.Parameter; statements.Add(new AssignmentStatement(new MemberBinding(this.currentClosureLocal, f), p)); } return newBlock; }
public Block CreateClosureClassInstance(Method method) { Class closureClassTemplate = method.Scope.ClosureClass; if (closureClassTemplate == null) { Debug.Fail("method.Scope.ClosureClass == null"); return null; } Block newBlock = new Block(); StatementList statements = new StatementList(1); newBlock.Statements = statements; newBlock.HasLocals = true; //At this point any base or chained constructors have been called and future references to parameters must happen via the closure MemberList scopeMembers = method.Scope.Members; for (int i = 0, n = scopeMembers.Count; i < n; i++) { Member m = scopeMembers[i]; Field f = m as Field; if (f == null || f.Type is Reference) continue; f.DeclaringType = closureClassTemplate; //This signals that the parameter field now must bind to the closure field, not the actual parameter closureClassTemplate.Members.Add(f); } Class closureClass = method.Scope.ClosureClass; if (closureClass.TemplateParameters != null && closureClass.TemplateParameters.Count > 0) closureClass = (Class)closureClass.GetTemplateInstance(this.currentType, method.TemplateParameters); this.currentClosureLocal = new Local(Identifier.For("SS$Closure Class Local"+method.UniqueKey), closureClass, newBlock); ExpressionList arguments = new ExpressionList(); if (method.Scope.ThisField != null){ Expression thisValue = method.ThisParameter; TypeNode t = method.Scope.ThisTypeInstance; if (t != null && t.IsValueType) thisValue = new AddressDereference(thisValue, t); arguments.Add(thisValue); } ParameterList pars = method.Parameters; for (int i = 0, n = pars == null ? 0 : pars.Count; i < n; i++) { Parameter p = pars[i]; if (p == null || p.Type == null || (p.Type is Reference)) continue; arguments.Add(p); } statements.Add(new AssignmentStatement(this.currentClosureLocal, new Construct(new MemberBinding(null, closureClass.GetConstructors()[0]), arguments))); return newBlock; }
public override Expression VisitAddressDereference(AddressDereference addr) { throw new ApplicationException("unimplemented"); }
public virtual Differences VisitAddressDereference(AddressDereference/*!*/ addr1, AddressDereference addr2) { Differences differences = new Differences(addr1, addr2); if (addr1 == null || addr2 == null){ if (addr1 != addr2) differences.NumberOfDifferences++; else differences.NumberOfSimilarities++; return differences; } AddressDereference changes = (AddressDereference)addr2.Clone(); AddressDereference deletions = (AddressDereference)addr2.Clone(); AddressDereference insertions = (AddressDereference)addr2.Clone(); Differences diff = this.VisitExpression(addr1.Address, addr2.Address); if (diff == null){Debug.Assert(false); return differences;} changes.Address = diff.Changes as Expression; deletions.Address = diff.Deletions as Expression; insertions.Address = diff.Insertions as Expression; Debug.Assert(diff.Changes == changes.Address && diff.Deletions == deletions.Address && diff.Insertions == insertions.Address); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; if (addr1.Alignment == addr2.Alignment) differences.NumberOfSimilarities++; else differences.NumberOfDifferences++; if (addr1.Volatile == addr2.Volatile) differences.NumberOfSimilarities++; else differences.NumberOfDifferences++; if (differences.NumberOfDifferences == 0){ differences.Changes = null; differences.Deletions = null; differences.Insertions = null; }else{ differences.Changes = changes; differences.Deletions = deletions; differences.Insertions = insertions; } return differences; }
public override Expression VisitPostfixExpression(PostfixExpression pExpr){ if (pExpr == null) return null; if (this.typeSystem.IsNullableType(pExpr.Type)) return VisitLiftedPostfixExpression(pExpr); StatementList statements = new StatementList(); BlockExpression result = new BlockExpression(new Block(statements)); LRExpression lrExpr = this.VisitTargetExpression(pExpr.Expression) as LRExpression; if (lrExpr == null) return null; LocalList locals = lrExpr.Temporaries; ExpressionList subs = lrExpr.SubexpressionsToEvaluateOnce; for (int i = 0, n = locals.Count; i < n; i++) statements.Add(new AssignmentStatement(locals[i], subs[i],pExpr.SourceContext)); TypeNode rType = pExpr.Type; EnumNode eType = rType as EnumNode; if (eType != null) rType = eType.UnderlyingType; Local temp = new Local(Identifier.Empty, rType); Expression e = this.typeSystem.AutoDereferenceCoercion(lrExpr.Expression); statements.Add(new AssignmentStatement(temp, this.VisitExpression(e), pExpr.SourceContext)); Expression newVal = null; if (pExpr.OperatorOverload != null){ ExpressionList arguments = new ExpressionList(1); arguments.Add(this.VisitExpression(lrExpr.Expression)); newVal = new MethodCall(new MemberBinding(null, pExpr.OperatorOverload), arguments, NodeType.Call, rType); }else{ Expression one = Literal.Int32One; if (rType == SystemTypes.Int64 || rType == SystemTypes.UInt64) one = Literal.Int64One; else if (rType == SystemTypes.Double) one = Literal.DoubleOne; else if (rType == SystemTypes.Single) one = Literal.SingleOne; else if (rType is Pointer){ Literal elementType = new Literal(((Pointer)rType).ElementType, SystemTypes.Type); UnaryExpression sizeOf = new UnaryExpression(elementType, NodeType.Sizeof, SystemTypes.Int32); one = PureEvaluator.EvalUnaryExpression(elementType, sizeOf); if (one == null) one = sizeOf; } newVal = new BinaryExpression(temp, one, pExpr.Operator, rType is Pointer ? rType : one.Type); newVal = this.typeSystem.ExplicitCoercion(newVal, lrExpr.Type, this.TypeViewer); } Expression target = this.VisitTargetExpression(lrExpr.Expression); MethodCall mcall = target as MethodCall; if (mcall != null){ mcall.Operands.Add(newVal); statements.Add(new ExpressionStatement(mcall)); }else if (target != null){ if (target.Type is Reference){ Local temp2 = new Local(Identifier.Empty, rType); statements.Add(new AssignmentStatement(temp2, newVal)); newVal = temp2; target = new AddressDereference(target, rType); } statements.Add(new AssignmentStatement(target, newVal,pExpr.SourceContext)); } statements.Add(new ExpressionStatement(temp)); result.Type = pExpr.Type; result.SourceContext = pExpr.SourceContext; result.Block.SourceContext = pExpr.SourceContext; return result; }
protected virtual Expression StandardImplicitCoercion(Expression source, bool sourceIsNonNullType, TypeNode sourceType, bool targetIsNonNullType, TypeNode targetType, TypeNode originalTargetType, TypeViewer typeViewer){ if (Literal.IsNullLiteral(source)) { if (this.IsNullableType(targetType)) { Local temp = new Local(targetType); StatementList statements = new StatementList(); BlockExpression result = new BlockExpression(new Block(statements)); statements.Add(new AssignmentStatement(new AddressDereference(new UnaryExpression(temp, NodeType.AddressOf), targetType), new Literal(null, CoreSystemTypes.Object))); statements.Add(new ExpressionStatement(temp)); return result; } if (targetType.IsTemplateParameter && !targetType.IsReferenceType) { // Check for reference constraint this.HandleError(source, Error.TypeVarCantBeNull, targetType.Name.Name); return new Local(targetType); } } //Identity coercion if (sourceType == targetType && (!targetIsNonNullType || (targetIsNonNullType == sourceIsNonNullType))) return source; ITypeParameter stp = sourceType as ITypeParameter; ITypeParameter ttp = targetType as ITypeParameter; if (stp != null && ttp != null && stp.ParameterListIndex == ttp.ParameterListIndex && stp.DeclaringMember == ttp.DeclaringMember && (!targetIsNonNullType || (targetIsNonNullType == sourceIsNonNullType))) return source; if (source is This && targetType != null && sourceType == targetType.Template && targetType.IsNotFullySpecialized) //TODO: add check for sourceType.TemplateParameters == targetType.TemplateArguments return source; //Dereference source Reference sr = sourceType as Reference; if (sr != null){ sourceType = sr.ElementType; Pointer pType = targetType as Pointer; if (pType != null && this.StandardImplicitCoercionFromTo(null, sourceType, pType.ElementType, typeViewer)) return source; else if (pType != null && pType.ElementType == SystemTypes.Void) return source; bool sourceIsThis = source is This; source = new AddressDereference(source, sourceType, source.SourceContext); source.Type = sourceType; sourceIsNonNullType = this.IsNonNullType(sourceType); sourceType = TypeNode.StripModifier(sourceType, SystemTypes.NonNullType); //Special case for coercion of this in template class if (sourceIsThis && targetType != null && sourceType == targetType.Template && targetType.IsNotFullySpecialized) //TODO: add check for sourceType.TemplateParameters == targetType.TemplateArguments return source; } //Identity coercion after dereference if (sourceType == targetType && (!targetIsNonNullType || (targetIsNonNullType == sourceIsNonNullType))) return source; //Special case for null literal if (Literal.IsNullLiteral(source)){ if (targetIsNonNullType) return ImplicitNonNullCoercion(this.ErrorHandler, source, originalTargetType); if (targetType is ITypeParameter && this.useGenerics) return new BinaryExpression(source, new Literal(targetType, SystemTypes.Type), NodeType.UnboxAny); if (!targetType.IsValueType || targetType.Template == SystemTypes.GenericBoxed) return new Literal(null, targetType, source.SourceContext); if (this.IsNullableType(targetType)) return new Local(StandardIds.NewObj, targetType, source.SourceContext); TypeAlias tAlias = targetType as TypeAlias; if (tAlias != null){ if (tAlias.RequireExplicitCoercionFromUnderlyingType) return null; source = this.ImplicitCoercion(source, tAlias.AliasedType, typeViewer); if (source == null) return null; Method coercion = this.UserDefinedImplicitCoercionMethod(source, tAlias.AliasedType, targetType, false, typeViewer); if (coercion != null){ ExpressionList args = new ExpressionList(this.ImplicitCoercion(source, coercion.Parameters[0].Type, typeViewer)); return new MethodCall(new MemberBinding(null, coercion), args, NodeType.Call, coercion.ReturnType); } }else{ Method coercion = this.UserDefinedImplicitCoercionMethod(source, source.Type, targetType, true, typeViewer); if (coercion != null){ ExpressionList args = new ExpressionList(this.ImplicitCoercion(source, coercion.Parameters[0].Type, typeViewer)); return new MethodCall(new MemberBinding(null, coercion), args, NodeType.Call, coercion.ReturnType); } } this.HandleError(source, Error.CannotCoerceNullToValueType, this.GetTypeName(targetType)); return new Local(targetType); } //Special case for string literal if (source.NodeType == NodeType.Literal && sourceType == SystemTypes.String && (targetType.Template == SystemTypes.GenericNonNull || targetType.Template == SystemTypes.GenericInvariant) && this.GetStreamElementType(targetType, typeViewer) == SystemTypes.String) return this.ExplicitCoercion(source, targetType, typeViewer); //Implicit numeric coercions + implicit enumeration coercions + implicit constant expression coercions if (sourceType.IsPrimitive && sourceType != SystemTypes.String && (targetType.IsPrimitive || targetType == SystemTypes.Decimal || targetType is EnumNode)){ Expression primitiveCoercion = this.ImplicitPrimitiveCoercion(source, sourceType, targetType, typeViewer); if (primitiveCoercion != null) return primitiveCoercion; } //Implicit coercion from string literal to numbers or eums if (this.allowStringLiteralToOtherPrimitiveCoercion && sourceType == SystemTypes.String && (targetType.IsPrimitive || targetType == SystemTypes.Decimal || targetType is EnumNode)){ Expression primitiveCoercion = this.ImplicitPrimitiveCoercion(source, sourceType, targetType, typeViewer); if (primitiveCoercion != null) return primitiveCoercion; } //Implicit reference coercions if (TypeViewer.GetTypeView(typeViewer, sourceType).IsAssignableTo(targetType)){ if (targetIsNonNullType && !(sourceIsNonNullType) && !sourceType.IsValueType) { //Handling for non null types return ImplicitNonNullCoercion(this.ErrorHandler, source, originalTargetType); }else if (sourceType.IsValueType && !targetType.IsValueType){ if (sourceType.NodeType == NodeType.TypeUnion){ Debug.Assert(targetType == SystemTypes.Object); return this.CoerceTypeUnionToObject(source, typeViewer); } if (sourceType is TupleType){ if (targetType == SystemTypes.Object) return this.TupleCoercion(source, sourceType, targetType, false, typeViewer); }else if (targetType.Template != SystemTypes.GenericIEnumerable && this.GetStreamElementType(sourceType, typeViewer) != sourceType) return this.ExplicitCoercion(this.CoerceStreamToObject(source, sourceType, typeViewer), targetType, typeViewer); Expression e = new BinaryExpression(source, new MemberBinding(null, sourceType), NodeType.Box, targetType, source.SourceContext); e.Type = targetType; return e; }else if (this.useGenerics && (sourceType is TypeParameter || sourceType is ClassParameter)){ source = new BinaryExpression(source, new MemberBinding(null, sourceType), NodeType.Box, sourceType); if (targetType == SystemTypes.Object) return source; return new BinaryExpression(source, new MemberBinding(null, targetType), NodeType.UnboxAny, targetType); } else if (this.useGenerics && sourceType is ArrayType) { ArrayType sat = (ArrayType)sourceType; while (sat.ElementType is ArrayType) sat = (ArrayType)sat.ElementType; if (sat.ElementType is ITypeParameter) return new BinaryExpression(source, new MemberBinding(null, targetType), NodeType.Castclass, targetType, source.SourceContext); return source; }else return source; } //Special case for delegates if (targetType is DelegateNode) return this.CoerceToDelegate(source, sourceType, (DelegateNode)targetType, false, typeViewer); //Special case for type union to common base type if (sourceType.NodeType == NodeType.TypeUnion) return this.CoerceFromTypeUnion(source, (TypeUnion)sourceType, targetType, false, originalTargetType, typeViewer); //Special case for Type intersection target type if (targetType.NodeType == NodeType.TypeIntersection) return this.CoerceToTypeIntersection(source, sourceType, (TypeIntersection)targetType, false, typeViewer); //Special cases for typed streams Expression streamCoercion = this.StreamCoercion(source, sourceType, targetType, false, originalTargetType, typeViewer); if (streamCoercion != null) return streamCoercion; //Implicit tuple coercions return this.TupleCoercion(source, sourceType, targetType, false, typeViewer); }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression){ if (binaryExpression == null) return null; if (this.typeSystem.IsNullableType(binaryExpression.Type)){ switch(binaryExpression.NodeType){ case NodeType.Add: case NodeType.And: case NodeType.Ceq: case NodeType.Cgt: case NodeType.Cgt_Un: case NodeType.Clt: case NodeType.Clt_Un: case NodeType.Div: case NodeType.Ge: case NodeType.Gt: case NodeType.Mul: case NodeType.Le: case NodeType.Lt: case NodeType.Or: case NodeType.Rem: case NodeType.Sub: case NodeType.Xor: return this.VisitLiftedBinaryExpression(binaryExpression); } } switch(binaryExpression.NodeType){ case NodeType.Range: Expression range = new Construct(new MemberBinding(null,SystemTypes.Range.GetConstructor(SystemTypes.Int32,SystemTypes.Int32)),new ExpressionList(binaryExpression.Operand1, binaryExpression.Operand2),SystemTypes.Range); range.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(range); case NodeType.Maplet: Expression maplet = new Construct(new MemberBinding(null,SystemTypes.DictionaryEntry.GetConstructor(SystemTypes.Object,SystemTypes.Object)),new ExpressionList(binaryExpression.Operand1, binaryExpression.Operand2),SystemTypes.DictionaryEntry); maplet.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(maplet); case NodeType.Implies: Expression implies = new TernaryExpression(binaryExpression.Operand1, binaryExpression.Operand2, new Literal(true, SystemTypes.Boolean), NodeType.Conditional, SystemTypes.Boolean); implies.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(implies); case NodeType.Iff: Expression iff = new BinaryExpression(binaryExpression.Operand1, binaryExpression.Operand2, NodeType.Eq, SystemTypes.Boolean); iff.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(iff); case NodeType.LogicalAnd: if (binaryExpression.Operand1 is Local && binaryExpression.Operand2 is MethodCall) return this.VisitShortCircuitBitwiseOp(binaryExpression); Expression e = new TernaryExpression(binaryExpression.Operand1, binaryExpression.Operand2, new Literal(false, SystemTypes.Boolean), NodeType.Conditional, SystemTypes.Boolean); e.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(e); case NodeType.LogicalOr: if (binaryExpression.Operand1 is Local && binaryExpression.Operand2 is MethodCall) return this.VisitShortCircuitBitwiseOp(binaryExpression); e = new TernaryExpression(binaryExpression.Operand1, new Literal(true, SystemTypes.Boolean), binaryExpression.Operand2, NodeType.Conditional, SystemTypes.Boolean); e.SourceContext = binaryExpression.SourceContext; return this.VisitExpression(e); } binaryExpression.Operand1 = this.VisitExpression(binaryExpression.Operand1); binaryExpression.Operand2 = this.VisitExpression(binaryExpression.Operand2); TypeNode t = binaryExpression.Type; switch(binaryExpression.NodeType){ case NodeType.Add: case NodeType.Sub: DelegateNode delType = t as DelegateNode; if (delType != null){ ExpressionList args = new ExpressionList(2); args.Add(binaryExpression.Operand1); args.Add(binaryExpression.Operand2); MethodCall mcall = new MethodCall(new MemberBinding(null, Runtime.Combine), args, NodeType.Call, Runtime.Combine.ReturnType, binaryExpression.SourceContext); if (binaryExpression.NodeType == NodeType.Sub) ((MemberBinding)mcall.Callee).BoundMember = Runtime.Remove; binaryExpression = new BinaryExpression(mcall, new Literal(delType, SystemTypes.Type), NodeType.Castclass, t, binaryExpression.SourceContext); } break; case NodeType.Box: Literal lit = binaryExpression.Operand2 as Literal; if (lit != null){ TypeNode bt = lit.Value as TypeNode; if (bt != null) binaryExpression.Operand2 = lit = new Literal(this.VisitTypeReference(bt), lit.Type, lit.SourceContext); } break; case NodeType.ExplicitCoercion: return binaryExpression.Operand1; case NodeType.Castclass: if (t == null) return null; if (t.IsValueType){ binaryExpression.NodeType = NodeType.Unbox; AddressDereference dref = new AddressDereference(binaryExpression, t); dref.Type = t; return dref; }else if (t is Pointer) return this.NormalizeToPointerCoercion(binaryExpression); if (binaryExpression.Operand1 != null && binaryExpression.Operand1.Type != null && binaryExpression.Operand1.Type.IsValueType) binaryExpression.Operand1 = new BinaryExpression(binaryExpression.Operand1, new MemberBinding(null, binaryExpression.Operand1.Type), NodeType.Box, SystemTypes.Object); break; case NodeType.Comma:{ StatementList statements = new StatementList(2); Expression opnd1 = binaryExpression.Operand1; if (opnd1 != null && opnd1.Type != SystemTypes.Void) opnd1 = new UnaryExpression(opnd1, NodeType.Pop, SystemTypes.Void); statements.Add(new ExpressionStatement(opnd1)); statements.Add(new ExpressionStatement(binaryExpression.Operand2)); return new BlockExpression(new Block(statements), SystemTypes.Boolean); } case NodeType.Eq : case NodeType.Ge : case NodeType.Gt : case NodeType.Le : case NodeType.Lt : case NodeType.Ne : // HACK: This tells normalizer to leave the expression as it is, because I need to run evaluator over it if (this.WrapToBlockExpression){ Block pushTrue = new Block(null); Block done = new Block(null); StatementList statements = new StatementList(6); if (binaryExpression.Operand1.Type != null && binaryExpression.Operand2.Type != null && binaryExpression.Operand1.Type.IsPrimitiveUnsignedInteger && binaryExpression.Operand2.Type.IsPrimitiveUnsignedInteger) { statements.Add(new Branch(binaryExpression, pushTrue, binaryExpression.SourceContext, true)); } else statements.Add(new Branch(binaryExpression, pushTrue)); statements.Add(new ExpressionStatement(new Literal(false, SystemTypes.Boolean))); statements.Add(new Branch(null, done)); statements.Add(pushTrue); statements.Add(new ExpressionStatement(new Literal(true, SystemTypes.Boolean))); statements.Add(done); return new BlockExpression(new Block(statements), SystemTypes.Boolean, binaryExpression.SourceContext); } return binaryExpression; case NodeType.Is : if (binaryExpression.Operand2 is Literal) binaryExpression.Type = (TypeNode)((Literal) binaryExpression.Operand2).Value; else binaryExpression.Type = (TypeNode)((MemberBinding)binaryExpression.Operand2).BoundMember; binaryExpression.NodeType = NodeType.Isinst; if (this.useGenerics && binaryExpression.Operand1 != null && binaryExpression.Operand1.Type != null && binaryExpression.Operand1.Type.IsTemplateParameter) binaryExpression.Operand1 = new BinaryExpression(binaryExpression.Operand1, new Literal(binaryExpression.Operand1.Type), NodeType.Box); binaryExpression = new BinaryExpression(binaryExpression, new Literal(null, SystemTypes.Object), NodeType.Ne); goto case NodeType.Eq; case NodeType.NullCoalescingExpression: { Expression cachedOperand1 = binaryExpression.Operand1; if (cachedOperand1 == null || cachedOperand1.Type == null || binaryExpression.Operand2 == null) return null; StatementList statements = new StatementList(); if (!(cachedOperand1 is Local || cachedOperand1 is Parameter)) { Expression cachedOperand1Temp = cachedOperand1; cachedOperand1 = new Local(cachedOperand1.Type); statements.Add(new AssignmentStatement(cachedOperand1, cachedOperand1Temp)); } Local exprValue = new Local(binaryExpression.Type); Block pushValue = new Block(); Block done = new Block(); Expression operand1HasValue; Method hasValue = this.GetTypeView(binaryExpression.Operand1.Type).GetMethod(StandardIds.getHasValue); if (hasValue != null) operand1HasValue = new MethodCall(new MemberBinding(new UnaryExpression(cachedOperand1, NodeType.AddressOf), hasValue), null); else { operand1HasValue = new BinaryExpression(this.typeSystem.ImplicitCoercion(cachedOperand1, SystemTypes.Object), Literal.Null, NodeType.Ne); } statements.Add(new Branch(operand1HasValue, pushValue)); Expression operand2 = this.typeSystem.ImplicitCoercion(binaryExpression.Operand2, binaryExpression.Type); statements.Add(new AssignmentStatement(exprValue, operand2)); statements.Add(new Branch(null, done)); statements.Add(pushValue); Expression operand1Value = null; if (hasValue != null) { Method getValueOrDefault = this.GetTypeView(binaryExpression.Operand1.Type).GetMethod(StandardIds.GetValueOrDefault); operand1Value = new MethodCall(new MemberBinding(new UnaryExpression(cachedOperand1, NodeType.AddressOf), getValueOrDefault), null); operand1Value.Type = getValueOrDefault.ReturnType; operand1Value = this.typeSystem.ImplicitCoercion(operand1Value, binaryExpression.Type); statements.Add(new AssignmentStatement(exprValue, operand1Value)); } else { operand1Value = this.typeSystem.ImplicitCoercion(cachedOperand1, binaryExpression.Type); statements.Add(new AssignmentStatement(exprValue, operand1Value)); } statements.Add(done); statements.Add(new ExpressionStatement(exprValue)); return new BlockExpression(new Block(statements), binaryExpression.Type, binaryExpression.SourceContext); } case NodeType.Shr : t = binaryExpression.Operand1.Type; if (t == SystemTypes.Char || t.IsUnsignedPrimitiveNumeric) binaryExpression.NodeType = NodeType.Shr_Un; break; } return binaryExpression; }
public virtual void VisitTypeswitchCaseList(TypeswitchCaseList oldCases, BlockList targets, StatementList statements, Block nextStatement, Local temp){ for (int i = 0, n = oldCases.Count; i < n; i++){ TypeswitchCase tcase = oldCases[i]; StatementList stats = new StatementList(3); Block b = new Block(stats); if (tcase != null){ Expression expr = null; if (tcase.LabelType.IsValueType) expr = new AddressDereference(new BinaryExpression(temp, new Literal(tcase.LabelType, SystemTypes.Type), NodeType.Unbox), tcase.LabelType); else expr = new BinaryExpression(temp, new Literal(tcase.LabelType, SystemTypes.Type), NodeType.Castclass); stats.Add(new AssignmentStatement(this.VisitTargetExpression(tcase.LabelVariable), expr)); stats.Add(this.VisitBlock(tcase.Body)); } stats.Add(new Branch(null, nextStatement)); statements.Add(b); targets.Add(b); } }
void Term(out Expression e) { TypeNode typ; Factor(null, out e); while (la.kind == 28 || la.kind == 37) { if (la.kind == 37) { Get(); Factor(e, out e); } else { Get(); ExpressionList es = new ExpressionList(); Expression a; Expr(out a); es.Add(a); while (la.kind == 23) { Get(); Expr(out a); es.Add(a); } Expect(29); Indexer idx = new Indexer(e, es); Expect(22); PType(out typ); idx.Type = typ; idx.ElementType = typ; Expect(24); if (TypeNode.StripModifiers(e.Type).IsPointerType) { e = new AddressDereference(new BinaryExpression(e, es[0], NodeType.Add, e.Type), typ); } else { e = idx; } } } }
protected virtual void VisitAddressDereference(AddressDereference adr) { if (adr == null) return; this.Visit(adr.Address); if (adr.Alignment > 0) this.ILGenerator.Emit(OpCodes.Unaligned, (byte)adr.Alignment); if (adr.Volatile) this.ILGenerator.Emit(OpCodes.Volatile); if (adr.Type == null) return; switch (adr.Type.typeCode){ case ElementType.Int8: this.ILGenerator.Emit(OpCodes.Ldind_I1); return; case ElementType.UInt8: this.ILGenerator.Emit(OpCodes.Ldind_U1); return; case ElementType.Int16: this.ILGenerator.Emit(OpCodes.Ldind_I2); return; case ElementType.Char: case ElementType.UInt16: this.ILGenerator.Emit(OpCodes.Ldind_U2); return; case ElementType.Int32: this.ILGenerator.Emit(OpCodes.Ldind_I4); return; case ElementType.UInt32: this.ILGenerator.Emit(OpCodes.Ldind_U4); return; case ElementType.Int64: case ElementType.UInt64: this.ILGenerator.Emit(OpCodes.Ldind_I8); return; case ElementType.UIntPtr: case ElementType.IntPtr: this.ILGenerator.Emit(OpCodes.Ldind_I); return; case ElementType.Single: this.ILGenerator.Emit(OpCodes.Ldind_R4); return; case ElementType.Double: this.ILGenerator.Emit(OpCodes.Ldind_R8); return; default: if (adr.Type.IsValueType && !(adr.Type is TypeParameter)){ this.ILGenerator.Emit(OpCodes.Ldobj, adr.Type.GetRuntimeType()); return; }else if (TypeNode.StripModifiers(adr.Type) is Pointer){ this.ILGenerator.Emit(OpCodes.Ldind_I); return; } this.ILGenerator.Emit(OpCodes.Ldind_Ref); return; } }
void Local(out Expression p) { p = null; int modifier = 0; /* 0 == none, 1 == address dereference, 2 == address of */ if (la.kind == 27 || la.kind == 30) { if (la.kind == 30) { Get(); modifier = 1; } else { Get(); modifier = 2; } } Expect(55); if (la.kind == 2) { Parameter(out p); } else if (la.kind == 49) { SpecialName(out p); } else SynErr(114); switch (modifier){ case 1: Debug.Assert(p.Type is Reference); Reference r = p.Type as Reference; p = new AddressDereference(p,r.ElementType); break; case 2: TypeNode newType = p.Type.GetReferenceType(); p = new UnaryExpression(p,NodeType.AddressOf,newType); break; default: /* nothing to do */ break; } }
private static string addrderef2str(AddressDereference ad) { return("*" + expression2str(ad.Address, false)); }
public override Expression VisitAddressDereference(AddressDereference addr) { if (addr == null) return null; Expression expr = addr.Address = this.VisitExpression(addr.Address); if (expr == null) return null; TypeNode exprType = expr.Type; if (exprType == null) return null; exprType = TypeNode.StripModifiers(exprType); Reference refType = exprType as Reference; if (refType != null) { // Change to highlight an issue: elementType can be an optional modifier, // in which case pointerType will be null. Is this the intention? TypeNode elementType = refType.ElementType;//TypeNode.StripModifiers(refType.ElementType); Pointer pointerType = elementType as Pointer; if (pointerType != null) { exprType = elementType; expr = addr.Address = this.typeSystem.AutoDereferenceCoercion(expr); } } if (!(exprType is Pointer || exprType is Reference || exprType.Template == SystemTypes.GenericBoxed || ((expr is Base) && exprType == SystemTypes.ValueType) || ((expr is This || expr is ImplicitThis) && exprType.IsValueType))) { this.HandleError(expr, Error.CannotDeferenceNonPointerType, this.GetTypeName(exprType)); return null; } if (exprType is Pointer && ((Pointer)exprType).ElementType == SystemTypes.Void) { this.HandleError(addr, Error.VoidError); return null; } int i = addr.Alignment; if (i > 0 && !(i == 1 || i == 2 || i == 4)) addr.Alignment = -1; //It is up to the source language to complain. return addr; }
public virtual Expression VisitAddressDereference(AddressDereference addr1, AddressDereference addr2) { if (addr1 == null) return null; if (addr2 == null) addr1.Address = this.VisitExpression(addr1.Address, null); else addr1.Address = this.VisitExpression(addr1.Address, addr2.Address); return addr1; }
public Method methodToInferPostFrom = null; //if set, Visit tries to infer a postcondition for method. public override StatementList VisitStatementList(StatementList statements) { if (statements == null) return null; foreach (Statement stat in statements) { Return r = stat as Return; if (r != null && r.Expression != null) { //Statement return E; found. Test admissibility of E as a witness. WitnessFromCodeAdmissibilityVisitor admis = new WitnessFromCodeAdmissibilityVisitor(); try { admis.VisitExpression(r.Expression); this.Witnesses.Add(r.Expression); //witness found, otherwise exception would have been thrown #region add inferred postconditions if needed TypeNode retType = (methodToInferPostFrom == null || methodToInferPostFrom.ReturnType == null) ? null : methodToInferPostFrom.ReturnType; if (r == statements[0] && retType != null && (retType.IsObjectReferenceType || retType.IsPrimitiveComparable)) { //the return statement is the first statement of the body. //We would like to add ensures result == r.Expression; However, we have to be careful, for 2 reasons. //1: == cannot be applied to structs and generic types. Note that we already tested that we do not return a struct. //2: result might be the implicitly boxed version of r.Expression (e.g., public object m() {returns 5;}), in which case result == r.Expression does not hold (in particular at runtime) //To account for 2, we have to box/unbox result and r.Expression as necessary //If r.Expression is a generic type, we have to distinguish cases !(r.Expression is System.ValueType) or (r.Expression is int) and act accordingly //(We do not (yet) support cases where r.Expression is a valueType other than an int, but they could be handled along the same lines.) if (methodToInferPostFrom.Contract == null) { methodToInferPostFrom.Contract = new MethodContract(methodToInferPostFrom); } SourceContext scInferred = methodToInferPostFrom.Name.SourceContext; //can't set the sourcetext, so error message will be confusing...but then again, the idea is that this can never crash //Duplicate the return expression to avoid sharing problems Duplicator dup = new Duplicator(this.methodToInferPostFrom.DeclaringType.DeclaringModule, this.methodToInferPostFrom.DeclaringType); Expression returnInEq = dup.VisitExpression(r.Expression); //needed for casting/boxing/unboxing MemberBinding intType = new MemberBinding(null, SystemTypes.Int32); Literal objectLit = new Literal(SystemTypes.Object, SystemTypes.Type); Literal intLit = new Literal(SystemTypes.Int32, SystemTypes.Type); Expression resultBinding = new ReturnValue(methodToInferPostFrom.ReturnType, scInferred); Expression resultInEq = resultBinding; if (r.Expression.NodeType == NodeType.Box) { //if the return expression has been (implicitly) boxed, unbox both it and result returnInEq = (returnInEq as BinaryExpression).Operand1; //as we have the return expression in hand, unboxing is easy //adjust resultInEq to (returnInEq.Type)resultInEq (i.e., add an unbox), using an explicit coercion BinaryExpression resultUnboxed = new BinaryExpression(resultInEq, intType, NodeType.Unbox, SystemTypes.Int32.GetReferenceType(), scInferred); //gets type System.Int32@ AddressDereference resultDeref = new AddressDereference(resultUnboxed, returnInEq.Type, scInferred); resultInEq = new BinaryExpression(resultDeref, intLit, NodeType.ExplicitCoercion, SystemTypes.Int32, scInferred); } if (returnInEq.Type != null && (returnInEq.Type.IsObjectReferenceType || returnInEq.Type.IsPrimitiveComparable)) { //returnInEq is not a user-defined struct (to which we can't apply ==) Expression eq = null; //holds the postcondition that is added if (!(isGenericTypeThatCanBeStruct(returnInEq.Type))) { //== can be applied to returnInEq. Therefore, it can also be applied to resultInEq, which is of a supertype (i.e., not generic type, not a struct). eq = new BinaryExpression(resultInEq, returnInEq, NodeType.Eq, SystemTypes.Boolean, scInferred); } else { #region adjust eq to compensate for generics //insert ensures !(returnInEq is System.ValueType) ==> (object)resultInEq == (object)returnInEq; //and ensures returnInEq is int ==> (int)(object)resultInEq == (int)(object)returnInEq; //the cast to object is needed to allow application of == and the cast to int. //Note that resultInEq.Type is known to also be a generic type as it is a supertype. //(and note that in this case, there was no unboxing) #region set up the antecedent !(returnInEq is System.ValueType) TypeNode theType = SystemTypes.ValueType; //antecedent: !(r.Expression is System.ValueType) Expression ante = new BinaryExpression(r.Expression, new Literal(theType, SystemTypes.Type), NodeType.Is, SystemTypes.Boolean, scInferred); ante = new UnaryExpression(ante, NodeType.LogicalNot, SystemTypes.Boolean, scInferred); #endregion #region adjust resultInEq and returnInEq to (object)resultInEq and (object)returnInEq //adjust resultInEq to (object)result, so that it can be used in == //that means Box it to T, then ExplicitCast it to Object. MemberBinding boxType = new MemberBinding(null, returnInEq.Type); //could also use method return type BinaryExpression resultBoxed = new BinaryExpression(resultBinding, boxType, NodeType.Box, returnInEq.Type, scInferred); resultInEq = new BinaryExpression(resultBoxed, objectLit, NodeType.ExplicitCoercion, SystemTypes.Object, scInferred); //adjust returnInEq to (object)returnInEq BinaryExpression returnBoxed = new BinaryExpression(returnInEq, boxType, NodeType.Box, returnInEq.Type, scInferred); returnInEq = new BinaryExpression(returnBoxed, objectLit, NodeType.ExplicitCoercion, SystemTypes.Object, scInferred); #endregion //Add first ensures; ensures ante ==> resultInEq == returnInEq; eq = new BinaryExpression(resultInEq, returnInEq, NodeType.Eq, SystemTypes.Boolean, scInferred); Expression impl = new BinaryExpression(ante, eq, NodeType.Implies, scInferred); EnsuresNormal firstPost = new EnsuresNormal(impl); firstPost.SourceContext = scInferred; methodToInferPostFrom.Contract.Ensures.Add(firstPost); //Now add ensures returnInEq is int ==> (int)(object)resultInEq == (int)(object)returnInEq; //antecedent: r.Expression is int Expression secondAnte = new BinaryExpression(r.Expression, intLit, NodeType.Is, SystemTypes.Boolean, scInferred); #region adjust resultInEq and returnInEq to (int)resultInEq and (int)returnInEq //set resultInSecondEq to (int)resultInEq, i.e., to (int)(object)result //this requires an unbox to int32@, then an adress-deref to int32, then an explicitcast to int32 //note that if we unbox to type Int32 directly, we get a "operation could destabilize the runtime" warining from the checkin tests BinaryExpression resultUnboxed = new BinaryExpression(resultInEq, intType, NodeType.Unbox, SystemTypes.Int32.GetReferenceType(), scInferred); //gets type System.Int32@ AddressDereference resultDeref = new AddressDereference(resultUnboxed, SystemTypes.Int32, scInferred); BinaryExpression resultInSecondEq = new BinaryExpression(resultDeref, intLit, NodeType.ExplicitCoercion, SystemTypes.Int32, scInferred); //adjust returnInEq to (int)returnInEq BinaryExpression returnUnboxed = new BinaryExpression(returnInEq, intType, NodeType.Unbox, SystemTypes.Int32.GetReferenceType(), scInferred); AddressDereference returnDeref = new AddressDereference(returnUnboxed, SystemTypes.Int32, scInferred); BinaryExpression returnInSecondEq = new BinaryExpression(returnDeref, intLit, NodeType.ExplicitCoercion, SystemTypes.Int32, scInferred); #endregion Expression secondEq = new BinaryExpression(resultInSecondEq, returnInSecondEq, NodeType.Eq, SystemTypes.Boolean, scInferred); eq = new BinaryExpression(secondAnte, secondEq, NodeType.Implies, SystemTypes.Boolean, scInferred); //(Ab)use eq to hold the implication #endregion } //Add the constructed equality as a postcondition. EnsuresNormal newPost = new EnsuresNormal(eq); newPost.SourceContext = scInferred; methodToInferPostFrom.Contract.Ensures.Add(newPost); } //else don't generate a postcondition, can't apply == to a user-defined struct } #endregion } catch (ApplicationException e) { ApplicationException dumme = e; } //witness not admissible ('using' e to avoid warning) } } return statements; }
public override Expression VisitAddressDereference(AddressDereference addr) { if (addr == null) return null; return base.VisitAddressDereference((AddressDereference)addr.Clone()); }
public override Expression VisitBinaryExpression(BinaryExpression binaryExpression){ if (binaryExpression == null) return null; bool opnd1IsInst = binaryExpression.Operand1 != null && binaryExpression.Operand1.NodeType == NodeType.Isinst; binaryExpression = (BinaryExpression)base.VisitBinaryExpression(binaryExpression); if (binaryExpression == null) return null; Expression opnd1 = binaryExpression.Operand1; Expression opnd2 = binaryExpression.Operand2; Literal lit = opnd2 as Literal; TypeNode t = lit == null ? null : lit.Value as TypeNode; if (binaryExpression.NodeType == NodeType.Castclass /*|| binaryExpression.NodeType == NodeType.ExplicitCoercion*/){ //See if castclass must become box or unbox if (t != null){ if (t.IsValueType){ AddressDereference adref = new AddressDereference(new BinaryExpression(opnd1, lit, NodeType.Unbox), t); adref.Type = t; return adref; } if (opnd1 != null && opnd1.Type != null && opnd1.Type.IsValueType){ return new BinaryExpression(opnd1, new MemberBinding(null, opnd1.Type), NodeType.Box, t); } } }else if (binaryExpression.NodeType == NodeType.Unbox){ if (opnd1 != null && opnd1.Type != null && opnd1.Type.IsValueType) return opnd1; #if ExtendedRuntime }else if (binaryExpression.NodeType == NodeType.Box){ if (t != null && !(t is ITypeParameter) && t.IsReferenceType && !t.IsPointerType) { // using pointer types is a Sing# extension return opnd1; } #endif }else if (binaryExpression.NodeType == NodeType.Eq) { //For value types, turn comparisons against null into false if (lit != null && lit.Value == null && opnd1 != null && opnd1.Type != null && opnd1.Type.IsValueType) return Literal.False; lit = opnd1 as Literal; if (lit != null && lit.Value == null && opnd2 != null && opnd2.Type != null && opnd2.Type.IsValueType) return Literal.False; }else if (binaryExpression.NodeType == NodeType.Ne){ //For value types, turn comparisons against null into true if (lit != null && lit.Value == null && opnd1 != null && opnd1.Type != null && opnd1.Type.IsValueType){ if (opnd1IsInst && opnd1.Type == CoreSystemTypes.Boolean) return opnd1; return Literal.True; } lit = opnd1 as Literal; if (lit != null && lit.Value == null && opnd2 != null && opnd2.Type != null && opnd2.Type.IsValueType) return Literal.True; }else if (binaryExpression.NodeType == NodeType.Isinst){ //Do not emit isinst instruction if opnd1 is a value type. if (opnd1 != null && opnd1.Type != null && opnd1.Type.IsValueType){ if (opnd1.Type == t) return Literal.True; else return Literal.False; } } return binaryExpression; }
public override Expression VisitAddressDereference(AddressDereference addr) { if (this._string == null){ this._string = new StringBuilder(); } this._string.Append("::$Deref{"); Expression e = base.VisitAddressDereference (addr); this._string.Append("}"); return e; }
public virtual Expression VisitAddressDereference(AddressDereference addr){ if (addr == null) return null; addr.Address = this.VisitExpression(addr.Address); return addr; }
protected virtual Expression StandardExplicitCoercionHelper(ErrorHandler savedErrorHandler, Expression source, bool sourceIsNonNullType, TypeNode sourceType, bool targetIsNonNullType, TypeNode targetType, TypeNode originalTargetType, TypeViewer typeViewer){ //Identity coercion if (sourceType == targetType && (!targetIsNonNullType || (targetIsNonNullType == sourceIsNonNullType))){ if (sourceType.IsPrimitiveNumeric){ Expression e = this.ExplicitPrimitiveCoercionHelper(source, sourceType, targetType); if (e == null) return source; e.Type = targetType; return e; } return source; } //Dereference source Reference sr = sourceType as Reference; if (sr != null && targetType is Pointer) return source; if (sr != null && source.NodeType != NodeType.AddressOf){ sourceType = sr.ElementType; source = new AddressDereference(source, sourceType, source.SourceContext); sourceType = TypeNode.StripModifier(sourceType, SystemTypes.NonNullType); } //Get rid of Nullable wrapper if (this.IsNullableType(sourceType)){ Method getValue = TypeViewer.GetTypeView(typeViewer, sourceType).GetMethod(Identifier.For("get_Value")); sourceType = this.RemoveNullableWrapper(sourceType); source = new MethodCall(new MemberBinding(source, getValue), null, NodeType.Call, sourceType, source.SourceContext); } //Identity coercion after dereference if (sourceType == targetType && (!targetIsNonNullType || (targetIsNonNullType == sourceIsNonNullType))){ if (sourceType.IsPrimitiveNumeric){ source = this.ExplicitPrimitiveCoercionHelper(source, sourceType, targetType); if (source == null) return null; source.Type = targetType; } return source; } //Special case for type union if (sourceType.NodeType == NodeType.TypeUnion) return this.CoerceFromTypeUnion(source, (TypeUnion)sourceType, targetType, true, originalTargetType, typeViewer); //Special case for null literal if (source.NodeType == NodeType.Literal && ((Literal)source).Value == null){ if (targetType.IsTemplateParameter && !targetType.IsReferenceType) { // Check for reference constraint //this.HandleError(source, Error.TypeVarCantBeNull, targetType.Name.Name); return null; } if (targetIsNonNullType) { //savedErrorHandler.HandleError(source, Error.CannotCoerceNullToNonNullType, savedErrorHandler.GetTypeName(targetType)); return ExplicitNonNullCoercion(source, originalTargetType); } if (targetType is ITypeParameter && sourceType == SystemTypes.Object && this.useGenerics) return new BinaryExpression(source, new Literal(targetType, SystemTypes.Type), NodeType.UnboxAny); if (!targetType.IsValueType || targetType.Template == SystemTypes.GenericBoxed) return new Literal(null, targetType, source.SourceContext); TypeAlias tAlias = targetType as TypeAlias; if (tAlias != null){ source = this.ExplicitCoercion(source, tAlias.AliasedType, typeViewer); if (source == null) return null; Method coercion = this.UserDefinedExplicitCoercionMethod(source, tAlias.AliasedType, targetType, false, originalTargetType, typeViewer); if (coercion != null){ ExpressionList args = new ExpressionList(this.ImplicitCoercion(source, coercion.Parameters[0].Type, typeViewer)); return new MethodCall(new MemberBinding(null, coercion), args, NodeType.Call, coercion.ReturnType); } } return null; } //Explicit reference coercions if (TypeViewer.GetTypeView(typeViewer, sourceType).IsAssignableTo(targetType)){ //Handling for non null types if (targetIsNonNullType && !sourceIsNonNullType && !sourceType.IsValueType) { //savedErrorHandler.HandleError(source, Error.CoercionToNonNullTypeMightFail, savedErrorHandler.GetTypeName(targetType)); return ExplicitNonNullCoercion(source, originalTargetType); } if (targetType == SystemTypes.Object && sourceType.Template == SystemTypes.GenericIEnumerable) return this.CoerceStreamToObject(source, sourceType, typeViewer); if (sourceType.IsValueType && !targetType.IsValueType){ if (sourceType.NodeType == NodeType.TypeUnion){ Debug.Assert(targetType == SystemTypes.Object); return this.CoerceTypeUnionToObject(source, typeViewer); } if (sourceType is TupleType){ if (targetType == SystemTypes.Object) return this.TupleCoercion(source, sourceType, targetType, true, typeViewer); }else if (this.GetStreamElementType(sourceType, typeViewer) != sourceType) return this.ExplicitCoercion(this.CoerceStreamToObject(source, sourceType, typeViewer), targetType, typeViewer); return new BinaryExpression(source, new MemberBinding(null, sourceType), NodeType.Box, targetType); }else if (this.useGenerics && sourceType is ITypeParameter){ source = new BinaryExpression(source, new MemberBinding(null, sourceType), NodeType.Box, sourceType); if (targetType == SystemTypes.Object) return source; return new BinaryExpression(source, new MemberBinding(null, targetType), NodeType.UnboxAny, targetType); }else return source; } //Special case for typed streams Expression streamCoercion = this.StreamCoercion(source, sourceType, targetType, true, originalTargetType, typeViewer); if (streamCoercion != null) return streamCoercion; //Down casts if (!targetType.IsPointerType && !sourceType.IsPointerType && TypeViewer.GetTypeView(typeViewer, targetType).IsAssignableTo(sourceType)){ if (!sourceType.IsValueType){ if (targetType.NodeType == NodeType.TypeUnion) return this.CoerceObjectToTypeUnion(source, (TypeUnion)targetType, typeViewer); if (source.NodeType == NodeType.Literal && ((Literal)source).Value == null) return source; if (targetType.IsValueType){ Expression e = new AddressDereference(new BinaryExpression(source, new MemberBinding(null, targetType), NodeType.Unbox, targetType.GetReferenceType()), targetType); e.Type = targetType; return e; }else{ NodeType op = this.useGenerics && (targetType is ClassParameter || targetType is TypeParameter) ? NodeType.UnboxAny : NodeType.Castclass; Expression e = new BinaryExpression(source, new MemberBinding(null, targetType), op, source.SourceContext); e.Type = originalTargetType; //Handling for non null types if (targetIsNonNullType && !sourceIsNonNullType){ //savedErrorHandler.HandleError(source, Error.CoercionToNonNullTypeMightFail, savedErrorHandler.GetTypeName(targetType)); return ExplicitNonNullCoercion(e, originalTargetType); } return e; } } } //Special case for casts to and from interfaces if ((sourceType.NodeType == NodeType.Interface && !targetType.IsSealed) || (targetType.NodeType == NodeType.Interface && !(sourceType.IsSealed || (sourceType is Pointer) || (sourceType is ArrayType && this.GetStreamElementType(targetType, typeViewer) == targetType)))){ Expression e = new BinaryExpression(source, new MemberBinding(null, targetType), NodeType.Castclass, source.SourceContext); e.Type = targetType; return e; } //Explicit numeric coercions + explicit enumeration coercions + explicit constant expression coercions Expression primitiveConversion = this.ExplicitPrimitiveCoercion(source, sourceType, targetType); if (primitiveConversion != null) return primitiveConversion; //Special case for decimal if (targetType == SystemTypes.Decimal && this.ImplicitCoercionFromTo(sourceType, targetType, typeViewer)) return this.ImplicitCoercion(source, targetType, typeViewer); //Special case for delegates if (targetType is DelegateNode) return this.CoerceToDelegate(source, sourceType, (DelegateNode)targetType, true, typeViewer); //Special case for type union if (targetType.NodeType == NodeType.TypeUnion) return this.CoerceToTypeUnion(source, sourceType, (TypeUnion)targetType, typeViewer); //Special case for Type intersection target type if (targetType.NodeType == NodeType.TypeIntersection) return this.CoerceToTypeIntersection(source, sourceType, (TypeIntersection)targetType, false, typeViewer); //Tuple coercion return this.TupleCoercion(source, sourceType, targetType, true, typeViewer); }
public virtual Expression VisitAddressDereference(AddressDereference addr, AddressDereference changes, AddressDereference deletions, AddressDereference insertions){ this.UpdateSourceContext(addr, changes); if (addr == null) return changes; if (changes != null){ if (deletions == null || insertions == null) Debug.Assert(false); else{ addr.Address = this.VisitExpression(addr.Address, changes.Address, deletions.Address, insertions.Address); addr.Alignment = changes.Alignment; addr.Volatile = changes.Volatile; } }else if (deletions != null) return null; return addr; }
/// <summary> /// Can be called after Checker.VisitExpression to have expressions of type "reference" /// be automatically dereferenced /// </summary> public virtual Expression AutoDereferenceCoercion(Expression expression) { if (expression == null) return null; if (expression.NodeType == NodeType.AddressOf || expression.NodeType == NodeType.RefAddress || expression.NodeType == NodeType.OutAddress) { return expression; } UnaryExpression unexpr = expression as UnaryExpression; if (unexpr != null && unexpr.NodeType == NodeType.Parentheses) { unexpr.Operand = this.AutoDereferenceCoercion(unexpr.Operand); return unexpr; } Reference rt = expression.Type as Reference; if (rt != null) { expression = new AddressDereference(expression, rt.ElementType, expression.SourceContext); } return expression; }