public InvocationTypeInferenceRules() : base(CompilerContext.Current) { var Array_EnumerableConstructor = Map(Methods.Of <IEnumerable, Array>(Builtins.array)); var Array_TypedEnumerableConstructor = Map(Methods.Of <Type, IEnumerable, Array>(Builtins.array)); var MultiDimensionalArray_TypedConstructor = Map(Methods.Of <Type, int[], Array>(Builtins.matrix)); RegisterTypeInferenceRuleFor( MultiDimensionalArray_TypedConstructor, (invocation, method) => { IType type = TypeSystemServices.GetReferencedType(invocation.Arguments[0]); if (type == null) { return(null); } return(type.MakeArrayType(invocation.Arguments.Count - 1)); }); RegisterTypeInferenceRuleFor( Array_EnumerableConstructor, (invocation, method) => { IType enumeratorItemType = TypeSystemServices.GetEnumeratorItemType(TypeSystemServices.GetExpressionType(invocation.Arguments[0])); if (TypeSystemServices.ObjectType == enumeratorItemType) { return(null); } invocation.Target.Entity = Array_TypedEnumerableConstructor; invocation.ExpressionType = Array_TypedEnumerableConstructor.ReturnType; invocation.Arguments.Insert(0, CodeBuilder.CreateReference(enumeratorItemType)); return(enumeratorItemType.MakeArrayType(1)); }); }
override public void LeaveForStatement(ForStatement node) { IType enumeratorType = GetExpressionType(node.Iterator); IType enumeratorItemType = TypeSystemServices.GetEnumeratorItemType(enumeratorType); DeclarationCollection declarations = node.Declarations; Block body = new Block(node.LexicalInfo); InternalLocal iterator = CodeBuilder.DeclareLocal( _current, "___iterator" + _context.AllocIndex(), TypeSystemServices.IEnumeratorType); if (TypeSystemServices.IEnumeratorType.IsAssignableFrom(enumeratorType)) { body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(iterator), node.Iterator)); } else { // ___iterator = <node.Iterator>.GetEnumerator() body.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference(iterator), CodeBuilder.CreateMethodInvocation( node.Iterator, IEnumerable_GetEnumerator))); } // while __iterator.MoveNext(): WhileStatement ws = new WhileStatement(node.LexicalInfo); ws.Condition = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateReference(iterator), IEnumerator_MoveNext); Expression current = CodeBuilder.CreateMethodInvocation( CodeBuilder.CreateReference(iterator), IEnumerator_get_Current); if (1 == declarations.Count) { // item = __iterator.Current ws.Block.Add( CodeBuilder.CreateAssignment( CodeBuilder.CreateReference((InternalLocal)declarations[0].Entity), current)); } else { UnpackExpression(ws.Block, CodeBuilder.CreateCast( enumeratorItemType, current), node.Declarations); } ws.Block.Add(node.Block); body.Add(ws); ReplaceCurrentNode(body); }