// // Our constructor // public Iterator(ParametersBlock block, IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) : base(block, TypeManager.bool_type, block.StartLocation) { this.OriginalMethod = method; this.OriginalIteratorType = iterator_type; this.IsEnumerable = is_enumerable; this.Host = host; this.type = method.ReturnType; }
public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent) { FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt); current_flow_branching = branching; return branching; }
/* * Completes the anonymous method processing, if lambda_expr is null, this * means that we have a Statement instead of an Expression embedded */ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) { AnonymousMethodExpression retval; if (async_block) anon_block.IsAsync = true; current_anonymous_method.Block = anon_block; retval = current_anonymous_method; async_block = (bool) oob_stack.Pop (); current_variable = (BlockVariable) oob_stack.Pop (); current_local_parameters = (ParametersCompiled) oob_stack.Pop (); current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); return retval; }
public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt) : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc) { }
// // Recreates a top level block from parameters block. Used for // compiler generated methods where the original block comes from // explicit child block. This works for already resolved blocks // only to ensure we resolve them in the correct flow order // public ToplevelBlock (ParametersBlock source, ParametersCompiled parameters) : base (source, parameters) { this.compiler = source.TopBlock.compiler; top_block = this; }
public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock) { this.ctx = ctx; this.ParametersBlock = parametersBlock; DefiniteAssignment = new DefiniteAssignmentBitSet (); }
public AnonymousMethodBody (ParametersCompiled parameters, ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, Location loc) : base (block, return_type, loc) { this.type = delegate_type; this.parameters = parameters; }
protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b) { return new AnonymousMethodBody (p, b, return_type, delegate_type, loc); }
public ParameterInfo (ParametersBlock block, int index) { this.block = block; this.index = index; }
public Block (Block parent, Flags flags, Location start, Location end) { if (parent != null) { // the appropriate constructors will fixup these fields ParametersBlock = parent.ParametersBlock; Explicit = parent.Explicit; } this.Parent = parent; this.flags = flags; this.StartLocation = start; this.EndLocation = end; this.loc = start; statements = new List<Statement> (4); this.original = this; }
public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock, int definiteAssignmentLength) { this.ctx = ctx; this.ParametersBlock = parametersBlock; DefiniteAssignment = definiteAssignmentLength == 0 ? DefiniteAssignmentBitSet.Empty : new DefiniteAssignmentBitSet (definiteAssignmentLength); }
/* * Completes the anonymous method processing, if lambda_expr is null, this * means that we have a Statement instead of an Expression embedded */ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) { AnonymousMethodExpression retval; current_anonymous_method.Block = anon_block; retval = current_anonymous_method; current_variable = (BlockVariableDeclaration) oob_stack.Pop (); current_local_parameters = (ParametersCompiled) oob_stack.Pop (); current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); return retval; }
static Expression DoImplicitConversionStandard (ResolveContext ec, Expression expr, TypeSpec target_type, Location loc, bool explicit_cast, bool upconvert_only) { if (expr.eclass == ExprClass.MethodGroup){ if (!target_type.IsDelegate){ if (ec.FileType == SourceFileType.PlayScript && (target_type == ec.BuiltinTypes.Dynamic || target_type == ec.BuiltinTypes.Delegate)) { MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) { if (mg.Candidates.Count != 1) { ec.Report.Error (7021, loc, "Ambiguous overloaded methods `{0}' when assigning to Function or Object type", mg.Name); return null; } var ms = (MethodSpec)mg.Candidates[0]; var del_type = Delegate.CreateDelegateTypeFromMethodSpec(ec, ms, loc); // If return is "Delegate", we create a var args anonymous method which calls the target method.. if (del_type == ec.BuiltinTypes.Delegate) { var objArrayType = new ComposedCast ( new TypeExpression(ec.BuiltinTypes.Object, loc), ComposedTypeSpecifier.CreateArrayDimension (1, loc)); var parameters = new ParametersCompiled(new Parameter[] { new ParamsParameter(objArrayType, "args", null, loc) }, false); var dynCall = new AnonymousMethodExpression(expr.Location, parameters, new TypeExpression(ms.ReturnType, loc)); var block = new ParametersBlock (ec.CurrentBlock, parameters, expr.Location); dynCall.Block = block; var args = new Arguments (3); args.Add (new Argument(new TypeOf(new TypeExpression(ms.DeclaringType, loc), loc))); args.Add (new Argument(new StringLiteral(ec.BuiltinTypes, ms.Name, loc))); args.Add (new Argument(new SimpleName("args", loc))); var call = new Invocation (new MemberAccess(new MemberAccess(new SimpleName("PlayScript", loc), "Support", loc), "VarArgCall", loc), args); if (ms.ReturnType == ec.BuiltinTypes.Void) { block.AddStatement (new StatementExpression(call)); } else { block.AddStatement (new Return(call, loc)); } return dynCall.Resolve (ec); } else { // Otherwise cast to the specific delegate type return new ImplicitDelegateCreation (del_type, mg, loc).Resolve (ec); } } } return null; } // // Only allow anonymous method conversions on post ISO_1 // if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){ MethodGroupExpr mg = expr as MethodGroupExpr; if (mg != null) return new ImplicitDelegateCreation (target_type, mg, loc).Resolve (ec); } } TypeSpec expr_type = expr.Type; Expression e; if (expr_type == target_type) { if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod) return expr; return null; } // Auto convert types to type objects.. if (ec.FileType == SourceFileType.PlayScript && target_type.BuiltinType == BuiltinTypeSpec.Type.Type && expr is FullNamedExpression) { FullNamedExpression type_expr = (FullNamedExpression)expr; if (expr_type != null) { if (expr_type.MemberDefinition.Namespace == PsConsts.PsRootNamespace) { switch (expr_type.Name) { case "String": type_expr = new TypeExpression (ec.BuiltinTypes.String, type_expr.Location); break; case "Number": type_expr = new TypeExpression (ec.BuiltinTypes.Double, type_expr.Location); break; case "Boolean": type_expr = new TypeExpression (ec.BuiltinTypes.Double, type_expr.Location); break; } } else if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { type_expr = new TypeExpression (ec.Module.PredefinedTypes.AsObject.Resolve(), type_expr.Location); } } return new TypeOf (type_expr, expr.Location).Resolve (ec); } if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { // Implicitly cast references to bools in PlayScript if (ec.FileType == SourceFileType.PlayScript && target_type.BuiltinType == BuiltinTypeSpec.Type.Bool && ec.Target != Target.JavaScript) { var cast_args = new Arguments(1); cast_args.Add (new Argument(EmptyCast.Create(expr, ec.BuiltinTypes.Object))); // ec.Report.Warning (7164, 1, expr.Location, "Expensive reference conversion to bool"); return new Invocation(new MemberAccess(new MemberAccess(new SimpleName( PsConsts.PsRootNamespace, expr.Location), "Boolean_fn", expr.Location), "Boolean", expr.Location), cast_args).Resolve (ec); } switch (target_type.Kind) { case MemberKind.ArrayType: case MemberKind.Class: if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object) return EmptyCast.Create (expr, target_type); goto case MemberKind.Struct; case MemberKind.Struct: case MemberKind.Delegate: case MemberKind.Enum: case MemberKind.Interface: case MemberKind.TypeParameter: Arguments args = new Arguments (1); args.Add (new Argument (expr)); return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec); } return null; } if (target_type.IsNullableType) return ImplicitNulableConversion (ec, expr, target_type); // // Attempt to do the implicit constant expression conversions // Constant c = expr as Constant; if (c != null) { try { c = c.ConvertImplicitly (target_type, ec, upconvert_only); } catch { throw new InternalErrorException ("Conversion error", loc); } if (c != null) return c; } e = ImplicitNumericConversion (expr, expr_type, target_type, ec, upconvert_only); if (e != null) return e; e = ImplicitPlayScriptConversion (expr, target_type, ec, upconvert_only); if (e != null) return e; e = ImplicitReferenceConversion (expr, target_type, explicit_cast, ec, upconvert_only); if (e != null) return e; e = ImplicitBoxingConversion (expr, expr_type, target_type); if (e != null) return e; if (expr is IntegralConstant && target_type.IsEnum){ var i = (IntegralConstant) expr; // // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 // // An implicit enumeration conversion permits the decimal-integer-literal 0 // to be converted to any enum-type and to any nullable-type whose underlying // type is an enum-type // if (i.IsZeroInteger) { // Recreate 0 literal to remove any collected conversions return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type); } } if (ec.IsUnsafe) { var target_pc = target_type as PointerContainer; if (target_pc != null) { if (expr_type.IsPointer) { // // Pointer types are same when they have same element types // if (expr_type == target_pc) return expr; if (target_pc.Element.Kind == MemberKind.Void) return EmptyCast.Create (expr, target_type); //return null; } if (expr_type == InternalType.NullLiteral) return new NullPointer (target_type, loc); } } if (expr_type == InternalType.AnonymousMethod){ AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; if (ec.FileType == SourceFileType.PlayScript && (target_type == ec.BuiltinTypes.Dynamic || target_type == ec.BuiltinTypes.Delegate)) { var del_type = Delegate.CreateDelegateType (ec, ame.AsParameters, ame.AsReturnType.ResolveAsType(ec), loc); return new Cast(new TypeExpression(del_type, loc), expr, loc).Resolve(ec); } Expression am = ame.Compatible (ec, target_type); if (am != null) return am.Resolve (ec); } if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec) return expr; // // dynamic erasure conversion on value types // if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type); return null; }
public void CaptureParameter (ResolveContext ec, ParametersBlock.ParameterInfo parameterInfo, ParameterReference parameterReference) { if (!(this is StateMachine)) { ec.CurrentBlock.Explicit.HasCapturedVariable = true; } var hoisted = parameterInfo.Parameter.HoistedVariant; if (hoisted == null) { var storey = parameterInfo.Block.StateMachine ?? this; var hp = new HoistedParameter (storey, parameterReference); hoisted = hp; parameterInfo.Parameter.HoistedVariant = hoisted; if (storey.hoisted_params == null) storey.hoisted_params = new List<HoistedParameter> (2); storey.hoisted_params.Add (hp); } // // Register link between current block and parameter storey. It will // be used when setting up storey definition to deploy storey reference // when parameters are used from multiple blocks // if (ec.CurrentBlock.Explicit != parameterInfo.Block) { hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); } }
// // It's supposed to be used by method body implementation of anonymous methods // protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters) : base (null, 0, source.StartLocation, source.EndLocation) { this.parameters = parameters; this.statements = source.statements; this.scope_initializers = source.scope_initializers; this.resolved = true; this.unreachable = source.unreachable; this.am_storey = source.am_storey; ParametersBlock = this; // // Overwrite original for comparison purposes when linking cross references // between anonymous methods // original = source; }
protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ParametersBlock b) { return new LambdaMethod (p, b, returnType, delegateType, loc); }
public LambdaMethod (ParametersCompiled parameters, ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, Location loc) : base (parameters, block, return_type, delegate_type, loc) { }
public BlockScopeExpression (Expression child, ParametersBlock block) { this.child = child; this.block = block; }
protected AnonymousExpression (ParametersBlock block, TypeSpec return_type, Location loc) { this.ReturnType = return_type; this.block = block; this.loc = loc; }
protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters) : base (null, 0, source.StartLocation, source.EndLocation) { this.parameters = parameters; this.statements = source.statements; this.scope_initializers = source.scope_initializers; this.resolved = true; this.unreachable = source.unreachable; this.am_storey = source.am_storey; ParametersBlock = this; }
public void CaptureParameter (ResolveContext ec, ParametersBlock.ParameterInfo parameterInfo, ParameterReference parameterReference) { if (!(this is StateMachine)) { ec.CurrentBlock.Explicit.HasCapturedVariable = true; } var hoisted = parameterInfo.Parameter.HoistedVariant; if (parameterInfo.Block.StateMachine != null) { // // Another storey in same block exists but state machine does not // have parameter captured. We need to add it there as well to // proxy parameter value correctly. // if (hoisted == null && parameterInfo.Block.StateMachine != this) { var storey = parameterInfo.Block.StateMachine; hoisted = new HoistedParameter (storey, parameterReference); parameterInfo.Parameter.HoistedVariant = hoisted; if (storey.hoisted_params == null) storey.hoisted_params = new List<HoistedParameter> (); storey.hoisted_params.Add (hoisted); } // // Lift captured parameter from value type storey to reference type one. Otherwise // any side effects would be done on a copy // if (hoisted != null && hoisted.Storey != this && hoisted.Storey is StateMachine) { if (hoisted_local_params == null) hoisted_local_params = new List<HoistedParameter> (); hoisted_local_params.Add (hoisted); hoisted = null; } } if (hoisted == null) { hoisted = new HoistedParameter (this, parameterReference); parameterInfo.Parameter.HoistedVariant = hoisted; if (hoisted_params == null) hoisted_params = new List<HoistedParameter> (); hoisted_params.Add (hoisted); } // // Register link between current block and parameter storey. It will // be used when setting up storey definition to deploy storey reference // when parameters are used from multiple blocks // if (ec.CurrentBlock.Explicit != parameterInfo.Block) { hoisted.Storey.AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); } }
public void WrapIntoIterator (IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) { ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); pb.EndLocation = EndLocation; pb.statements = statements; var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable); am_storey = new IteratorStorey (iterator); statements = new List<Statement> (1); AddStatement (new Return (iterator, iterator.Location)); }