/// <summary> /// Need to visit closures as well /// </summary> public override void VisitConstruct(Construct cons) { if (cons == null) return; if (cons.Operands == null) return; if (cons.Operands.Count < 2) return; if (cons.Type.IsDelegateType()) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; var um = HelperMethods.Unspecialize(m); if (HelperMethods.IsAnonymousDelegate(um, this.CurrentType)) { this.VisitAnonymousDelegate(um, m); } } JustVisit: base.VisitConstruct(cons); }
public override void VisitConstruct(Construct cons) { if ((cons.Type.IsDelegateType())) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue != null) { MemberBinding mb = ue.Operand as MemberBinding; if (mb != null) { Method m = (Method) mb.BoundMember; if (HelperMethods.IsClosureMethod(this.containingType, m)) { if (HelperMethods.IsClosureType(this.containingType, m.DeclaringType)) { // Roslyn-based compiler changed non-capturing lambda caching. // Instead of storing delegate in a field like CS$<>9_CachedAnonymousMethodDelegate1 // Roslyn-based compiler generates a closure class called <>c with a set of instance // methods and a singleton instance. // This change allows to duplicate this new closure type if (HelperMethods.IsRoslynBasedStaticClosure(m.DeclaringType)) { TryAddTypeToMembersToDuplicate(m.DeclaringType); } } else { // Logic for pre-Roslyn compiler. // then there is no closure class, m is just a method the compiler // added to the class itself // we record the instance here, although we will eventually make a copy of the // template by making the method generic in its parent type type-parameters. MembersToDuplicate.Add(m); } } else { //Console.WriteLine("Not atomic closure part: {0}", m.FullName); var declaringTypeName = m.DeclaringType.Name.Name; var name = m.Name.Name; string message = String.Format( "DeclaringName should contain 'DisplayClass', <>c or Name should not have '__'. \r\nDeclaringTypeName: {0}, Name: {1}", declaringTypeName, name); Debug.Assert( declaringTypeName.Contains("DisplayClass") || declaringTypeName.Contains("<>c") || !name.Contains("__"), message); } } } } base.VisitConstruct(cons); }
/// <summary> /// If there is an anonymous delegate within a postcondition, then there /// will be a call to a delegate constructor. /// That call looks like "d..ctor(o,m)" where d is the type of the delegate. /// There are two cases depending on whether the anonymous delegate captured /// anything. In both cases, m is the method implementing the anonymous delegate. /// /// (1) It does capture something. Then o is the instance of the closure class /// implementing the delegate, and m is an instance method in the closure /// class. /// (2) It does *not* capture anything. Then o is the literal for null and /// m is a static method that was added directly to the class. /// /// This method will cause m to be visited to collect any old expressions /// that occur in it. But those old expressions are not turned into locals, /// but fields. The fields are created as either (1) members of the closure class, /// or (2) members of the class in which the method containing the contract /// containing the Old expression is defined. /// The fields are initialized when (1) the closure class instance is created, /// or (2) ... ??? (when!?) /// So set up enough state so that when those old expressions are visited, the /// correct ASTs can be built. /// </summary> /// <param name="cons">The AST representing the call to the constructor /// of the delegate type.</param> /// <returns>Whatever the base visitor returns</returns> public override Expression VisitConstruct(Construct cons) { if (cons.Type is DelegateNode) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; Contract.Assume(m != null); if (m.IsStatic) { // then there is no closure class, m is just a static method the compiler // added to the class itself goto JustVisit; } if (HelperMethods.IsCompilerGenerated(m)) { Local l = cons.Operands[0] as Local; if (l == null) goto JustVisit; // but then what is it?? TypeNode savedClosureClass = this.currentClosureClass; this.currentClosureClass = l.Type; if (savedClosureClass == null) { // then this is the top-level closure class // have to treat it special: it doesn't contain a field that points // to the top-level closure class. The field introduced to hold the value of the // old expression will be declared in this class. this.topLevelClosureClass = this.currentClosureClass; } else { // Find the field in this.closureClass that the C# compiler generated // to point to the top-level closure foreach (Member mem in this.currentClosureClass.Members) { Field f = mem as Field; if (f == null) continue; if (f.Type == this.topLevelClosureClass) { this.PointerToTopLevelClosureClass = f; break; } } } this.VisitBlock(m.Body); if (savedClosureClass == null) { this.topLevelClosureClass = null; } this.currentClosureClass = savedClosureClass; this.PointerToTopLevelClosureClass = null; } } JustVisit: return base.VisitConstruct(cons); }
/// <summary> /// If there is an anonymous delegate within a postcondition, then there /// will be a call to a delegate constructor. /// That call looks like "d..ctor(o,m)" where d is the type of the delegate. /// There are two cases depending on whether the anonymous delegate captured /// anything. In both cases, m is the method implementing the anonymous delegate. /// (1) It does capture something. Then o is the instance of the closure class /// implementing the delegate, and m is an instance method in the closure /// class. /// (2) It does *not* capture anything. Then o is the literal for null and /// m is a static method that was added directly to the class. /// /// This method will cause the method (i.e., m) to be visited to collect any /// Result<T>() expressions that occur in it. /// </summary> /// <param name="cons">The AST representing the call to the constructor /// of the delegate type.</param> /// <returns>Whatever the base visitor returns</returns> public override Expression VisitConstruct(Construct cons) { if (cons.Type is DelegateNode) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; if (!HelperMethods.IsCompilerGenerated(m)) goto JustVisit; Contract.Assume(m != null); m = Definition(m); this.delegateNestingLevel++; TypeNode savedClosureClass = this.currentClosureClassInstance; Method savedClosureMethod = this.currentClosureMethod; Expression savedCurrentAccessToTopLevelClosure = this.currentAccessToTopLevelClosure; try { this.currentClosureMethod = m; if (m.IsStatic) { this.currentClosureClassInstance = null; // no closure object } else { this.currentClosureClassInstance = cons.Operands[0].Type; if (savedClosureClass == null) { // Then this is the top-level closure class. this.topLevelClosureClassInstance = this.currentClosureClassInstance; this.topLevelClosureClassDefinition = Definition(this.topLevelClosureClassInstance); this.currentAccessToTopLevelClosure = new This(this.topLevelClosureClassDefinition); this.properlyInstantiatedFieldType = this.originalLocalForResult.Type; if (this.topLevelMethodFormals != null) { Contract.Assume(this.topLevelClosureClassDefinition.IsGeneric); Contract.Assume(topLevelClosureClassDefinition.TemplateParameters.Count >= this.topLevelMethodFormals.Count); // replace method type parameters in result properly with last n corresponding type parameters of closure class TypeNodeList closureFormals = topLevelClosureClassDefinition.TemplateParameters; if (closureFormals.Count > this.topLevelMethodFormals.Count) { int offset = closureFormals.Count - this.topLevelMethodFormals.Count; closureFormals = new TypeNodeList(this.topLevelMethodFormals.Count); for (int i = 0; i < this.topLevelMethodFormals.Count; i++) { closureFormals.Add(topLevelClosureClassDefinition.TemplateParameters[i + offset]); } } Duplicator dup = new Duplicator(this.declaringType.DeclaringModule, this.declaringType); Specializer spec = new Specializer(this.declaringType.DeclaringModule, topLevelMethodFormals, closureFormals); var type = dup.VisitTypeReference(this.originalLocalForResult.Type); type = spec.VisitTypeReference(type); this.properlyInstantiatedFieldType = type; } } else { while (currentClosureClassInstance.Template != null) currentClosureClassInstance = currentClosureClassInstance.Template; // Find the field in this.closureClass that the C# compiler generated // to point to the top-level closure foreach (Member mem in this.currentClosureClassInstance.Members) { Field f = mem as Field; if (f == null) continue; if (f.Type == this.topLevelClosureClassDefinition) { var consolidatedTemplateParams = this.currentClosureClassInstance.ConsolidatedTemplateParameters; TypeNode thisType; if (consolidatedTemplateParams != null && consolidatedTemplateParams.Count > 0) { thisType = this.currentClosureClassInstance.GetGenericTemplateInstance(this.assemblyBeingRewritten, consolidatedTemplateParams); } else { thisType = this.currentClosureClassInstance; } this.currentAccessToTopLevelClosure = new MemberBinding(new This(thisType), f); break; } } } } this.VisitBlock(m.Body); } finally { this.delegateNestingLevel--; this.currentClosureMethod = savedClosureMethod; this.currentClosureClassInstance = savedClosureClass; this.currentAccessToTopLevelClosure = savedCurrentAccessToTopLevelClosure; } } JustVisit: return base.VisitConstruct(cons); }
public override Expression VisitConstruct(Construct cons) { isMRNAO = true; return cons; }
public override Expression VisitConstruct(Construct cons) { hasCall = true; return cons; }
public override Expression VisitConstruct(Construct cons) { Write("new "); TypeExpression te = cons.Constructor.Type as TypeExpression; if (te != null) this.VisitExpression(te.Expression); else if (cons.Constructor.Type.FullName != null) Write(cons.Constructor.Type.FullName); else throw new NotImplementedException("Unexpected constructor style"); Write("("); this.VisitExpressionList(cons.Operands); Write(")"); return cons; }
internal Class CreateSerializerFor(TypeNode type) { // todo: look in the genCache for other serializer assemblies that may have already // created the serializer for this type and make an assembly reference to that // serializer instead of creating a complete duplicate. TypeNode saved = tempChecker.currentType; Class c = (Class)serializers[type]; if (c != null) return c; c = new Class(); c.Flags = TypeFlags.Class | TypeFlags.BeforeFieldInit; // copy the accessibility of the type we are serializing. c.Flags |= (type.Flags & (TypeFlags.Public | TypeFlags.NestedAssembly)); c.Name = Identifier.For(GetSerializerName(type)); c.Namespace = Identifier.For(GetSerializerNamespace(type)); c.DeclaringModule = this.module; c.Members = new MemberList(); c.Attributes = new AttributeList(); c.BaseClass = Runtime.XmlSerializer; tempChecker.currentType = c; InstanceInitializer ii = Runtime.XmlSerializerAttribute.GetConstructor(); MemberBinding mb = new MemberBinding(null, ii); mb.Type = Runtime.XmlSerializerAttribute; c.Attributes.Add(new AttributeNode(mb, null)); if (cunit != null) { cunit.Namespaces[0].Types.Add(c); } this.module.Types.Add(c); Identifier typeId = Identifier.For("type"); // what we are writing to. Identifier rootName = Identifier.For("rootName"); // what we are writing to. Identifier rootNamespace = Identifier.For("rootNamespace"); // what we are writing to. // Constructor Method constructor = new InstanceInitializer(); constructor.Name = StandardIds.Ctor; constructor.DeclaringType = c; constructor.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.SpecialName|MethodFlags.RTSpecialName; constructor.Parameters = new ParameterList(); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, typeId, SystemTypes.Type, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); constructor.ReturnType = SystemTypes.Void; c.Members.Add(constructor); // pass args thru to base XmlSerializer constructor. Block b = constructor.Body = new Block(new StatementList()); b.Statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor), new ExpressionList(typeId, rootName, rootNamespace), NodeType.Call))); //AddConsoleWrite(b.Statements, new Literal("Hello!!",SystemTypes.String)); // Serialize(T source, XmlSerializationWriter writer) method Identifier src = Identifier.For("source"); // object being serialized. Identifier writer = Identifier.For("writer"); // what we are writing to. Method serialize = new Method(); serialize.Name = Identifier.For("Serialize"); serialize.DeclaringType = c; serialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; serialize.Parameters = new ParameterList(); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, src, type, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, writer, Runtime.XmlSerializationWriter, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); serialize.ReturnType = SystemTypes.Void; c.Members.Add(serialize); // T Deserialize(XmlReader reader, bool required, out bool result) method Identifier reader = Identifier.For("reader"); // what we are reading from. Identifier required = Identifier.For("required"); // whether an object is required or not. Identifier result = Identifier.For("result"); // whether we found anything. Method deserialize = new Method(); deserialize.Name = Identifier.For("Deserialize"); deserialize.DeclaringType = c; deserialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; deserialize.Parameters = new ParameterList(); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, reader, Runtime.XmlSerializationReader, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, required, SystemTypes.Boolean, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.Out, result, SystemTypes.Boolean.GetReferenceType(), null, null)); deserialize.ReturnType = type; c.Members.Add(deserialize); // It is important that we add the serializer to the cache AFTER we create the methods, but // BEFORE we create the method bodies so that we can handle recurrsive calls to AddCallSerializer which // happens in recurrsive structures like "class Foo { public Foo f; }". Otherwise we'd get stuck in an // infinite loop. serializers[type] = c; // Body of serialize method. b = serialize.Body = new Block(new StatementList()); StatementList statements = b.Statements; if (!AddWriteSimpleType(type, statements, c, writer, src, rootName, rootNamespace)) { MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement")); call.Operands = new ExpressionList(); call.Operands.Add(rootName); call.Operands.Add(rootNamespace); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); Expression source = src; if (type.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, c), type); type = Checker.GetCollectionElementType(type); source = CastTo(src, type);//unbox it } if (type is TupleType) { AddWriteTuple(type as TupleType, statements, c, source, writer); } else if (type is TypeUnion) { AddWriteChoice(type as TypeUnion, statements, c, source, writer); } else if (IsStream(type)) { AddWriteStream(type, statements, c, source, writer); } else { SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); statements = AddCheckForNull(statements, Duplicate(src, c), type); AddWriteAttributes(statements, c, writer, source, validator); AddWriteContent(type, statements, c, writer, source, validator); } call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement")); call.Operands = new ExpressionList(); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); } // body of deserialize method. b = deserialize.Body = new Block(new StatementList()); statements = b.Statements; Local target = new Local(Identifier.Empty, type); if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } if (type is TupleType) { AddReadTuple(b, type as TupleType, statements, reader, target, required, result); } else if (type is TypeUnion) { AddReadChoice(b, type as TypeUnion, statements, reader, target, required, result); } else if (IsStream(type)) { AddReadStream(b, type, statements, reader, target, result); } else { if (type is TypeAlias) { type = ((TypeAlias)type).AliasedType; } // Then we are already positioned on the element to be deserialized. statements.Add(new AssignmentStatement(required, Literal.True)); if (!AddReadSimpleType(type, statements, reader, target, result, false)) { if (!type.IsValueType && !type.IsAbstract && type.GetConstructor() != null) { Construct cons = new Construct(new MemberBinding(null, type), new ExpressionList(), type); statements.Add(new AssignmentStatement(target, cons)); } SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); AddReadAttributes(type, statements, reader, target, validator); AddReadContent(c, b, type, statements, reader, target, required, result, validator); } } statements.Add(new Return(target)); tempChecker.currentType = saved; return c; }
public override Expression VisitConstruct(Construct cons) { if (cons == null) return null; // // Wrap all Zing allocations in a call to application.Allocate // Expression ptrAllocation; ZArray arrayNode = cons.Type as ZArray; if (visitingField) { if (arrayNode != null) ptrAllocation = Templates.GetExpressionTemplate("InitializerArrayPtrAllocation"); // Added by Jiri Adamek else if (((MemberBinding)cons.Constructor).Type is NativeZOM) ptrAllocation = Templates.GetExpressionTemplate("InitializerNativeZOMPtrAllocation"); // END of added code else ptrAllocation = Templates.GetExpressionTemplate("InitializerPtrAllocation"); } else { if (arrayNode != null) ptrAllocation = Templates.GetExpressionTemplate("ArrayPtrAllocation"); // Added by Jiri Adamek else if (((MemberBinding)cons.Constructor).Type is NativeZOM) ptrAllocation = Templates.GetExpressionTemplate("NativeZOMPtrAllocation"); // END of added code else ptrAllocation = Templates.GetExpressionTemplate("PtrAllocation"); } if (arrayNode != null) { if (arrayNode.Sizes == null) { // This is a variable-sized array Replacer.Replace(ptrAllocation, "_size", this.VisitExpression(cons.Operands[0])); } else { // This is a constant-sized array Replacer.Replace(ptrAllocation, "_size", new Literal(arrayNode.Sizes[0], SystemTypes.Int32)); } } Replacer.Replace(ptrAllocation, "_Constructor", cons.Type.Name); Replacer.Replace(ptrAllocation, "_ClassName", new Literal(cons.Type.Name.ToString(), SystemTypes.String)); return ptrAllocation; }
/// <summary> /// </summary> /// <param name="cons">Cloned</param> /// <returns></returns> public override Expression VisitConstruct(Construct cons) { ExpressionList operands = this.VisitExpressionList(cons.Operands); MemberBinding mb = this.VisitExpression(cons.Constructor) as MemberBinding; if (mb == null) return null; Debug.Assert(mb.TargetObject == null, "constructor target not null!"); if ( this.expandAllocations ) { // Now split the expression into 3: // allocTemp = new T; // allocTemp..ctor(args...); // allocTemp // For value types, the construction is even more involved: // valTemp = new VT; // allocTemp = &valTemp; // allocTemp..ctor(args...); // valTemp if (mb.BoundMember != null && mb.BoundMember.DeclaringType != null && mb.BoundMember.DeclaringType.IsValueType) { Variable valTemp = StackVariable.NEWValueTemp(mb.BoundMember.DeclaringType); Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType); AssignmentStatement new_stat = new AssignmentStatement(valTemp, newcons); new_stat.SourceContext = this.current_source_context; new_stats.Add(new_stat); Variable allocTemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType); new_stats.Add(new AssignmentStatement(allocTemp, new UnaryExpression(valTemp, NodeType.AddressOf, mb.BoundMember.DeclaringType.GetReferenceType()), NodeType.Nop)); mb.TargetObject = allocTemp; ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void)); call_stat.SourceContext = this.current_source_context; new_stats.Add(call_stat); return valTemp; } else { Variable vtemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType); Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType); AssignmentStatement new_stat = new AssignmentStatement(vtemp, newcons); new_stat.SourceContext = this.current_source_context; new_stats.Add(new_stat); mb.TargetObject = vtemp; ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void)); call_stat.SourceContext = this.current_source_context; new_stats.Add(call_stat); return vtemp; } } else { Construct newcons = new Construct(mb, operands, mb.BoundMember.DeclaringType); newcons.SourceContext = this.current_source_context; return newcons; } }
public override Expression VisitConstruct(Construct cons) { if (cons == null) return null; Construct result = (Construct)base.VisitConstruct(cons); result.Constructor.Type = (TypeNode)this.Visit(result.Constructor.Type); return result; }
public override Expression VisitConstruct(Construct cons) { if (cons == null) return cons; MemberBinding mb = cons.Constructor as MemberBinding; if (mb == null) return null; // // Verify that mb.BoundMember is a heap-allocated type // TypeNode tn = cons.Type; ZArray arrayNode = tn as ZArray; if (tn is Set || arrayNode != null || tn is Class || tn is Chan) { if (arrayNode != null) { ExpressionList el = cons.Operands; Debug.Assert(el.Count <= 1); if (arrayNode.Sizes == null) { // This is a variable-sized array. Check that there is exactly // one argument to the constructor of integer type. if (el.Count == 0) { this.HandleError(cons, Error.IntegerExpressionRequired); return null; } Expression e = (Expression)el[0]; if (e.Type != SystemTypes.Int32) { this.HandleError(cons, Error.IntegerExpressionRequired); return null; } } else { // This is a constant-sized array. Check that there is no // argument to the constructor. if (el.Count == 1) { this.HandleError(cons, Error.UnexpectedToken, new string[] { el[0].ToString() }); return null; } } } return cons; } else { this.HandleError(cons, Error.ExpectedComplexType); return null; } }
// Handle bodies of anonymous delegates public override void VisitConstruct(Construct cons) { if (cons.Type.IsDelegateType()) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue == null) goto JustVisit; MemberBinding mb = ue.Operand as MemberBinding; if (mb == null) goto JustVisit; Method m = mb.BoundMember as Method; if (HelperMethods.IsCompilerGenerated(m)) { bool savedInvisibleMemberRef = this.generatedMethodContainsInvisibleMemberReference; try { this.generatedMethodContainsInvisibleMemberReference = false; var unspecedM = HelperMethods.Unspecialize(m); var unspecedT = unspecedM.DeclaringType; Contract.Assert(unspecedT.Template == null); this.referencingType.Push(unspecedT); this.VisitBlock(unspecedM.Body); if (this.generatedMethodContainsInvisibleMemberReference) { // remove method (and all containing closure methods) savedInvisibleMemberRef = true; for (int i = 0; i < unspecedT.Members.Count; i++) { if (unspecedT.Members[i] == unspecedM) { unspecedT.Members[i] = null; break; } } } } finally { this.generatedMethodContainsInvisibleMemberReference = savedInvisibleMemberRef; this.referencingType.Pop(); } } } JustVisit: base.VisitConstruct(cons); }
public override void VisitConstruct(Construct cons) { if ((cons.Type.IsDelegateType())) { UnaryExpression ue = cons.Operands[1] as UnaryExpression; if (ue != null) { MemberBinding mb = ue.Operand as MemberBinding; if (mb != null) { Method m = (Method)mb.BoundMember; if (HelperMethods.IsClosureMethod(this.containingType, m) && !HelperMethods.IsClosureType(this.containingType, m.DeclaringType)) { // then there is no closure class, m is just a method the compiler // added to the class itself // we record the instance here, although we will eventually make a copy of the // template by making the method generic in its parent type type-parameters. MembersToDuplicate.Add(m); } else { //Console.WriteLine("Not atomic closure part: {0}", m.FullName); Debug.Assert(m.DeclaringType.Name.Name.Contains("DisplayClass") || !m.Name.Name.Contains("__")); } } } } base.VisitConstruct(cons); }
public virtual Expression VisitConstruct(Construct cons) { if (cons == null) return null; cons.Constructor = this.VisitExpression(cons.Constructor); cons.Operands = this.VisitExpressionList(cons.Operands); cons.Owner = this.VisitExpression(cons.Owner); return cons; }
public override void VisitConstruct(Construct cons) { if (cons == null) return; var memberBinding = cons.Constructor as MemberBinding; if (memberBinding != null && memberBinding.BoundMember != null && HelperMethods.DerivesFromException(memberBinding.BoundMember.DeclaringType)) { this.foundExceptionType = memberBinding.BoundMember.DeclaringType; } }
private Expression ParseNew(TokenSet followers){ SourceContext ctx = this.scanner.CurrentSourceContext; Debug.Assert(this.currentToken == Token.New); this.GetNextToken(); TypeNode allocator = null; if (this.currentToken == Token.LeftBracket) { this.GetNextToken(); if (this.currentToken == Token.RightBracket) { return this.ParseNewImplicitlyTypedArray(ctx, followers); } // parse [Delayed] annotation (or allocator) allocator = this.ParseBaseTypeExpression(null, followers|Token.RightBracket, false, false); if (allocator == null){this.SkipTo(followers, Error.None); return null;} this.Skip(Token.RightBracket); } if (this.currentToken == Token.LeftBrace) return this.ParseNewAnonymousTypeInstance(ctx, followers); Expression owner = null; // Allow owner argument for each constructor: "new <ow> ..." if (this.currentToken == Token.LessThan) { this.GetNextToken(); owner = this.ParsePrimaryExpression(followers | Token.GreaterThan); if (this.currentToken == Token.GreaterThan) this.GetNextToken(); } // Make it explicit that the base type stops at "!", which is handled by // the code below. TypeNode t = this.ParseBaseTypeExpression(null, followers|Parser.InfixOperators|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis|Token.LogicalNot, false, false); if (t == null){this.SkipTo(followers, Error.None); return null;} if (this.currentToken == Token.Conditional) { TypeNode type = t; t = new NullableTypeExpression(type); t.SourceContext = type.SourceContext; t.SourceContext.EndPos = this.scanner.endPos; this.GetNextToken(); }else if (this.currentToken == Token.LogicalNot){ TypeNode type = t; t = new NonNullableTypeExpression(type); t.SourceContext = type.SourceContext; t.SourceContext.EndPos = this.scanner.endPos; this.GetNextToken(); }else if (this.currentToken == Token.Multiply){ this.GetNextToken(); t = new PointerTypeExpression(t, t.SourceContext); t.SourceContext.EndPos = this.scanner.endPos; if (!this.inUnsafeCode) this.HandleError(t.SourceContext, Error.UnsafeNeeded); } ctx.EndPos = t.SourceContext.EndPos; // special hack [Delayed] in custom allocator position is used to mark the array as // a delayed construction. This annotation is used in the Definite Assignment analysis. // TypeExpression allocatorExp = allocator as TypeExpression; if (allocatorExp != null) { Identifier allocId = allocatorExp.Expression as Identifier; if (allocId != null && allocId.Name == "Delayed") { t = new RequiredModifierTypeExpression(t, TypeExpressionFor("Microsoft","Contracts","DelayedAttribute")); allocator = null; // not really a custom allocation } } int rank = this.ParseRankSpecifier(false, followers|Token.LeftBrace|Token.LeftBracket|Token.LeftParenthesis|Token.RightParenthesis); SourceContext lbCtx = ctx; while (rank > 0 && this.currentToken == Token.LeftBracket){ lbCtx = this.scanner.CurrentSourceContext; t = new ArrayTypeExpression(t, rank); rank = this.ParseRankSpecifier(false, followers|Token.LeftBrace|Token.LeftBracket); } if (rank > 0){ //new T[] {...} or new T[,] {{..} {...}...}, etc where T can also be an array type ConstructArray consArr = new ConstructArray(); consArr.SourceContext = ctx; consArr.ElementType = consArr.ElementTypeExpression = t; consArr.Rank = rank; if (this.currentToken == Token.LeftBrace) consArr.Initializers = this.ParseArrayInitializer(rank, t, followers); else{ if (Parser.UnaryStart[this.currentToken]) this.HandleError(Error.ExpectedLeftBrace); else this.HandleError(Error.MissingArraySize); while (Parser.UnaryStart[this.currentToken]){ this.ParseExpression(followers|Token.Comma|Token.RightBrace); if (this.currentToken != Token.Comma) break; this.GetNextToken(); } if (this.currentToken == Token.RightBrace) this.GetNextToken(); this.SkipTo(followers); } if (owner != null) { consArr.Owner = owner; } return consArr; } if (rank < 0){ //new T[x] or new T[x,y] etc. possibly followed by an initializer or element type rank specifier ConstructArray consArr = new ConstructArray(); consArr.SourceContext = ctx; consArr.Operands = this.ParseIndexList(followers|Token.LeftBrace|Token.LeftBracket, lbCtx, out consArr.SourceContext.EndPos); rank = consArr.Operands.Count; if (this.currentToken == Token.LeftBrace) consArr.Initializers = this.ParseArrayInitializer(rank, t, followers); else{ int elementRank = this.ParseRankSpecifier(true, followers); tryAgain: if (elementRank > 0) t = this.ParseArrayType(elementRank, t, followers); if (this.currentToken == Token.LeftBrace) consArr.Initializers = this.ParseArrayInitializer(rank, t, followers); else{ if (this.currentToken == Token.LeftBracket){ //new T[x][y] or something like that lbCtx = this.scanner.CurrentSourceContext; this.GetNextToken(); SourceContext sctx = this.scanner.CurrentSourceContext; this.ParseIndexList(followers, lbCtx, out sctx.EndPos); this.HandleError(sctx, Error.InvalidArray); elementRank = 1; goto tryAgain; }else this.SkipTo(followers); } } consArr.ElementType = consArr.ElementTypeExpression = t; consArr.Rank = rank; if (owner != null) { consArr.Owner = owner; } return consArr; } ExpressionList arguments = null; SourceContext lpCtx = this.scanner.CurrentSourceContext; bool sawLeftParenthesis = false; if (this.currentToken == Token.LeftParenthesis){ if (rank == 0 && t is NonNullableTypeExpression) { this.SkipTo(followers, Error.BadNewExpr); return null; } sawLeftParenthesis = true; this.GetNextToken(); arguments = this.ParseArgumentList(followers, lpCtx, out ctx.EndPos); }else if (this.currentToken == Token.LeftBrace){ Expression quant = this.ParseComprehension(followers); arguments = new ExpressionList(quant); }else{ this.SkipTo(followers, Error.BadNewExpr); Construct c = new Construct(); if (t is TypeExpression) c.Constructor = new MemberBinding(null, t, t.SourceContext); c.SourceContext = ctx; return c; } if (sawLeftParenthesis && this.currentToken == Token.LeftBrace){ } Construct cons = new Construct(new MemberBinding(null, t), arguments); cons.SourceContext = ctx; if (owner != null) cons.Owner = owner; return cons; }
void AddReadStream(Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression result){ // Read next element and figure out if it matches the stream element type, if so read it and add it to the list // If not, then return (throw an error if there are no items and the list is the non-empty type). // flexArray = new flexarray(); // while (reader.Read() && read.NodeType != XmlNodeType.EndElement) { // if (reader.NodeType == XmlNodeType.Element) { // readchild(flexarray); // } // } // target = flexArray; Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String, block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String, block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType, block); Local optional = new Local(Identifier.Empty, SystemTypes.Boolean, block); Local foundChild = new Local(Identifier.Empty, SystemTypes.Boolean, block); statements.Add(new AssignmentStatement(optional, Literal.False)); TypeNode eType = Checker.GetCollectionElementType(type); Local local = new Local(Identifier.Empty, eType, block); Method addMethod = null; Local localArray = null; if (type.Template == SystemTypes.GenericBoxed) { addMethod = null; // only needs one! } else if (Checker.IsGenericList(type)) { //TODO: this call is invalid if the eType is not public TypeNode flexArrayType = SystemTypes.GenericList.GetTemplateInstance(this.module, eType); localArray = new Local(Identifier.For("stream"+streamCount++), flexArrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, flexArrayType), new ExpressionList(), flexArrayType))); addMethod = flexArrayType.GetMethod(Identifier.For("Add"), eType); } else { TypeNode arrayType = SystemTypes.ArrayList; localArray = new Local(Identifier.Empty, arrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, arrayType), new ExpressionList(), arrayType))); addMethod = arrayType.GetMethod(Identifier.For("Add"), SystemTypes.Object); } Block whileBody = new Block(new StatementList()); MethodCall moveToContent = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()); BinaryExpression notAtEnd = new BinaryExpression(moveToContent, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notAtEnd, notEOF, NodeType.And), whileBody); statements.Add(w); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); StatementList trueStatements = whileBody.Statements; if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } trueStatements.Add(new AssignmentStatement(foundChild, Literal.False)); if (eType is TupleType || eType is TypeUnion || IsStream(eType)) { AddCallDeserializer(eType, trueStatements, reader, local, optional, foundChild); } else { AddReadChild(whileBody, trueStatements, Checker.GetDefaultElementName(eType), eType, local, reader, foundChild, true, false); } If ifFound = new If(new BinaryExpression(foundChild, Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); ifFound.TrueBlock.Statements.Add(new AssignmentStatement(result, Literal.True)); // set our result to true then. ifFound.FalseBlock.Statements.Add(new Exit()); // break out of loop then. trueStatements.Add(ifFound); if (addMethod == null) { trueStatements.Add(new AssignmentStatement(target, CastTo(local, type))); // box the result. trueStatements.Add(new Exit()); // break out of loop we have it! } else { MemberBinding addCall = new MemberBinding(localArray, addMethod); trueStatements.Add(new ExpressionStatement(new MethodCall(addCall, new ExpressionList(new Expression[1] {local})))); } // clear out the local, it is a struct of some sort. if (local.Type.IsValueType && ! local.Type.IsPrimitive) { trueStatements.Add(new AssignmentStatement(local, new Construct(new MemberBinding(null,local.Type), new ExpressionList(), local.Type))); } // end while // assign resulting array to the target object (if we have anything to assign). If ifResult = new If(new BinaryExpression(result, Literal.True, NodeType.Eq), new Block(new StatementList()), null); statements.Add(ifResult); statements = ifResult.TrueBlock.Statements; if (addMethod != null) { if (type is ArrayType) { // target = (type)localArray.ToArray(etype); Method toArray = SystemTypes.ArrayList.GetMethod(Identifier.For("ToArray"), SystemTypes.Type); ExpressionList args = new ExpressionList(); args.Add(new UnaryExpression(new Literal(eType, SystemTypes.Type), NodeType.Typeof, SystemTypes.Type)); statements.Add(new AssignmentStatement(target, CastTo(new MethodCall(new MemberBinding(localArray, toArray), args, NodeType.Callvirt, SystemTypes.Array), type))); } else if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { // Explicit coercion of IEnumerable to NonEmptyIEnumerable requires constructing // the NonEmptyIEnumerable object passing in the IEnumerable as an argument. TypeNode ienumtype = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type); Debug.Assert(ienumtype!=null); //TODO: this call is invalid if the eType is not public TypeNode nonEmptyIEnum = SystemTypes.GenericNonEmptyIEnumerable.GetTemplateInstance(this.module, eType); InstanceInitializer ii = nonEmptyIEnum.GetConstructor(ienumtype); Construct c = new Construct(new MemberBinding(null, ii), new ExpressionList(localArray), nonEmptyIEnum); statements.Add(new AssignmentStatement(target, c)); } else { statements.Add(new AssignmentStatement(target, localArray)); } } }
public override Expression VisitConstruct(Construct cons) { if (cons == null) return null; return base.VisitConstruct((Construct)cons.Clone()); }
public override Expression VisitConstruct(Construct cons) { Write("new "); this.VisitExpression(cons.Constructor); // This only happens for variable-length arrays, and only one // parameter is permitted. if (cons.Operands.Count > 0) { Write("["); this.VisitExpression(cons.Operands[0]); Write("]"); } return cons; }
public EventingVisitor(Action<Construct> visitConstruct) { VisitedConstruct += visitConstruct; } public event Action<Construct> VisitedConstruct; public override Expression VisitConstruct(Construct cons) { if (VisitedConstruct != null) VisitedConstruct(cons); return base.VisitConstruct(cons); }