// // Creates mcs arguments from dynamic argument info // public Compiler.Arguments CreateCompilerArguments(IEnumerable <CSharpArgumentInfo> info, DynamicMetaObject[] args) { var res = new Compiler.Arguments(args.Length); int pos = 0; // enumerates over args foreach (var item in info) { var expr = CreateCompilerExpression(item, args[pos++]); if (item.IsNamed) { res.Add(new Compiler.NamedArgument(item.Name, Compiler.Location.Null, expr, item.ArgumentModifier)); } else { res.Add(new Compiler.Argument(expr, item.ArgumentModifier)); } if (pos == args.Length) { break; } } return(res); }
protected override Expression CreateExpressionTree (ResolveContext ec, Type delegate_type) { if (ec.IsInProbingMode) return this; BlockContext bc = new BlockContext (ec.MemberContext, ec.CurrentBlock.Explicit, TypeManager.void_type); Expression args = Parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (delegate_type, loc)), arguments); }
protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) { if (ec.IsInProbingMode) return this; BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { CurrentAnonymousMethod = ec.CurrentAnonymousMethod }; Expression args = Parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (delegate_type, loc)), arguments); }
public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e) { Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length); for (int i = 0; i < e.Length; ++i) { if (e [i] != null) all.Add (new Argument (e[i])); } if (args != null) { foreach (Argument a in args.args) { Expression tree_arg = a.CreateExpressionTree (ec); if (tree_arg != null) all.Add (new Argument (tree_arg)); } } return all; }
public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec) { if ((modFlags & Modifier.RefOutMask) != 0) ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec); Arguments arguments = new Arguments (2); arguments.Add (new Argument (new TypeOf (parameter_type, Location))); arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location))); return new SimpleAssign (ExpressionTreeVariableReference (), Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location)); }
public void Resolve() { if (RootContext.Unsafe) { // // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] // when -unsafe option was specified // Location loc = Location.Null; MemberAccess system_security_permissions = new MemberAccess(new MemberAccess( new QualifiedAliasMember(QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); Arguments pos = new Arguments(1); pos.Add(new Argument(new MemberAccess(new MemberAccess(system_security_permissions, "SecurityAction", loc), "RequestMinimum"))); Arguments named = new Arguments(1); named.Add(new NamedArgument(new LocatedToken(loc, "SkipVerification"), (new BoolLiteral(true, loc)))); GlobalAttribute g = new GlobalAttribute(new NamespaceEntry(null, null, null), "assembly", new MemberAccess(system_security_permissions, "SecurityPermissionAttribute"), new Arguments[] { pos, named }, loc, false); g.AttachTo(this, this); if (g.Resolve() != null) { declarative_security = new ListDictionary(); g.ExtractSecurityPermissionSet(declarative_security); } } if (OptAttributes == null) { return; } // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types. if (!OptAttributes.CheckTargets()) { return; } ClsCompliantAttribute = ResolveAttribute(PredefinedAttributes.Get.CLSCompliant); if (ClsCompliantAttribute != null) { is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue(); } Attribute a = ResolveAttribute(PredefinedAttributes.Get.RuntimeCompatibility); if (a != null) { object val = a.GetPropertyValue("WrapNonExceptionThrows"); if (val != null) { wrap_non_exception_throws = (bool)val; } } }
public override Expression CreateExpressionTree (ResolveContext ec) { MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc); Arguments args = new Arguments (3); args.Add (new Argument (new TypeOf (type, loc))); if (method_group.InstanceExpression == null) args.Add (new Argument (new NullLiteral (loc))); else args.Add (new Argument (method_group.InstanceExpression)); args.Add (new Argument (method_group.CreateExpressionTree (ec))); Expression e = new Invocation (ma, args).Resolve (ec); if (e == null) return null; e = Convert.ExplicitConversion (ec, e, type, loc); if (e == null) return null; return e.CreateExpressionTree (ec); }
protected override Expression ResolveConversions (ResolveContext ec) { // // LAMESPEC: Under dynamic context no target conversion is happening // This allows more natual dynamic behaviour but breaks compatibility // with static binding // if (target is RuntimeValueExpression) return this; TypeSpec target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists (ec, source, target_type)) { source = Convert.ImplicitConversion (ec, source, target_type, loc); return this; } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b == null) { if (source is ReducedExpression) b = ((ReducedExpression) source).OriginalExpression as Binary; else if (source is ReducedExpression.ReducedConstantExpression) { b = ((ReducedExpression.ReducedConstantExpression) source).OriginalExpression as Binary; } else if (source is Nullable.LiftedBinaryOperator) { var po = ((Nullable.LiftedBinaryOperator) source); if (po.UserOperator == null) b = po.Binary; } else if (source is TypeCast) { b = ((TypeCast) source).Child as Binary; } } if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists (ec, right, target_type)) { source = Convert.ExplicitConversion (ec, source, target_type, loc); return this; } } if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { Arguments arg = new Arguments (1); arg.Add (new Argument (source)); return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec); } right.Error_ValueCannotBeConverted (ec, target_type, false); return null; }
public override Expression CreateExpressionTree (ResolveContext ec) { BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType); Expression args = parameters.CreateExpressionTree (bc, loc); Expression expr = Block.CreateExpressionTree (ec); if (expr == null) return null; Arguments arguments = new Arguments (2); arguments.Add (new Argument (expr)); arguments.Add (new Argument (args)); return CreateExpressionFactoryCall (ec, "Lambda", new TypeArguments (new TypeExpression (type, loc)), arguments); }
protected override bool DoDefineMembers() { PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> bs; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; PredefinedMember <MethodSpec> sm; bool has_task_return_type = false; var pred_members = Module.PredefinedMembers; if (return_type.Kind == MemberKind.Void) { builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; bf = pred_members.AsyncVoidMethodBuilderCreate; bs = pred_members.AsyncVoidMethodBuilderStart; sr = pred_members.AsyncVoidMethodBuilderSetResult; se = pred_members.AsyncVoidMethodBuilderSetException; sm = pred_members.AsyncVoidMethodBuilderSetStateMachine; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; bs = pred_members.AsyncTaskMethodBuilderStart; sr = pred_members.AsyncTaskMethodBuilderSetResult; se = pred_members.AsyncTaskMethodBuilderSetException; sm = pred_members.AsyncTaskMethodBuilderSetStateMachine; task = pred_members.AsyncTaskMethodBuilderTask.Get(); } else { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; bf = pred_members.AsyncTaskMethodBuilderGenericCreate; bs = pred_members.AsyncTaskMethodBuilderGenericStart; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; se = pred_members.AsyncTaskMethodBuilderGenericSetException; sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine; task = pred_members.AsyncTaskMethodBuilderGenericTask.Get(); has_task_return_type = true; } set_result = sr.Get(); set_exception = se.Get(); builder_factory = bf.Get(); builder_start = bs.Get(); var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; var set_statemachine = sm.Get(); if (!builder_type.Define() || !istate_machine.Define() || set_result == null || builder_factory == null || set_exception == null || set_statemachine == null || builder_start == null || !Module.PredefinedTypes.INotifyCompletion.Define()) { Report.Error(1993, Location, "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); return(base.DoDefineMembers()); } var bt = builder_type.TypeSpec; // // Inflate generic Task types // if (has_task_return_type) { var task_return_type = return_type.TypeArguments; if (mutator != null) { task_return_type = mutator.Mutate(task_return_type); } bt = bt.MakeGenericType(Module, task_return_type); set_result = MemberCache.GetMember(bt, set_result); set_exception = MemberCache.GetMember(bt, set_exception); set_statemachine = MemberCache.GetMember(bt, set_statemachine); if (task != null) { task = MemberCache.GetMember(bt, task); } } builder = AddCompilerGeneratedField("$builder", new TypeExpression(bt, Location)); var set_state_machine = new Method(this, new TypeExpression(Compiler.BuiltinTypes.Void, Location), Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC, new MemberName("SetStateMachine"), ParametersCompiled.CreateFullyResolved( new Parameter(new TypeExpression(istate_machine.TypeSpec, Location), "stateMachine", Parameter.Modifier.NONE, null, Location), istate_machine.TypeSpec), null); ToplevelBlock block = new ToplevelBlock(Compiler, set_state_machine.ParameterInfo, Location); block.IsCompilerGenerated = true; set_state_machine.Block = block; Members.Add(set_state_machine); if (!base.DoDefineMembers()) { return(false); } // // Fabricates SetStateMachine method // // public void SetStateMachine (IAsyncStateMachine stateMachine) // { // $builder.SetStateMachine (stateMachine); // } // var mg = MethodGroupExpr.CreatePredefined(set_statemachine, bt, Location); mg.InstanceExpression = new FieldExpr(builder, Location); var param_reference = block.GetParameterReference(0, Location); param_reference.Type = istate_machine.TypeSpec; param_reference.eclass = ExprClass.Variable; var args = new Arguments(1); args.Add(new Argument(param_reference)); set_state_machine.Block.AddStatement(new StatementExpression(new Invocation(mg, args))); if (has_task_return_type) { hoisted_return = LocalVariable.CreateCompilerGenerated(bt.TypeArguments[0], StateMachineMethod.Block, Location); } return(true); }
public override Expression DoResolveLValue(ResolveContext rc, Expression right_side) { if (right_side == EmptyExpression.OutAccess.Instance) { right_side.DoResolveLValue (rc, this); return null; } if (DoResolveCore (rc)) { setter_args = new Arguments (Arguments.Count + 1); setter_args.AddRange (Arguments); setter_args.Add (new Argument (right_side)); setter = CreateCallSiteBinder (rc, setter_args, true); } eclass = ExprClass.Variable; return this; }
void EmitOnCompleted(EmitContext ec, Expression awaiter, bool unsafeVersion) { var pm = Module.PredefinedMembers; PredefinedMember <MethodSpec> predefined; bool has_task_return_type = false; if (return_type.Kind == MemberKind.Void) { predefined = unsafeVersion ? pm.AsyncVoidMethodBuilderOnCompletedUnsafe : pm.AsyncVoidMethodBuilderOnCompleted; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderOnCompletedUnsafe : pm.AsyncTaskMethodBuilderOnCompleted; } else if (return_type.IsGenericTask) { predefined = unsafeVersion ? pm.AsyncTaskMethodBuilderGenericOnCompletedUnsafe : pm.AsyncTaskMethodBuilderGenericOnCompleted; has_task_return_type = true; } else { var parameters = new ParametersImported( new [] { new ParameterData(null, Parameter.Modifier.REF), new ParameterData(null, Parameter.Modifier.REF) }, new [] { new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), new TypeParameterSpec(1, null, SpecialConstraint.None, Variance.None, null) }, false); var on_completed_sign = unsafeVersion ? MemberFilter.Method("AwaitUnsafeOnCompleted", 2, parameters, Compiler.BuiltinTypes.Void) : MemberFilter.Method("AwaitOnCompleted", 2, parameters, Compiler.BuiltinTypes.Void); predefined = new PredefinedMember <MethodSpec> (Module, return_type.MemberDefinition.GetAsyncMethodBuilder(), on_completed_sign); has_task_return_type = return_type.IsGeneric; } var on_completed = predefined.Resolve(Location); if (on_completed == null) { return; } if (has_task_return_type) { on_completed = MemberCache.GetMember <MethodSpec> (set_result.DeclaringType, on_completed); } on_completed = on_completed.MakeGenericMethod(this, awaiter.Type, ec.CurrentType); var mg = MethodGroupExpr.CreatePredefined(on_completed, on_completed.DeclaringType, Location); mg.InstanceExpression = new FieldExpr(builder, Location) { InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, Location) }; var args = new Arguments(2); args.Add(new Argument(awaiter, Argument.AType.Ref)); args.Add(new Argument(new CompilerGeneratedThis(CurrentType, Location), Argument.AType.Ref)); using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) { mg.EmitCall(ec, args, true); } }
public void EmitPrologue(EmitContext ec) { awaiter = ((AsyncTaskStorey)machine_initializer.Storey).AddAwaiter(expr.Type, loc); var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); Label skip_continuation = ec.DefineLabel(); using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) { // // awaiter = expr.GetAwaiter (); // fe_awaiter.EmitAssign(ec, expr, false, false); Expression completed_expr; if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); Arguments dargs = new Arguments(1); dargs.Add(new Argument(fe_awaiter)); completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc); dargs = new Arguments(1); dargs.Add(new Argument(completed_expr)); completed_expr = new DynamicConversion(ec.Module.Compiler.BuiltinTypes.Bool, 0, dargs, loc).Resolve(rc); } else { var pe = PropertyExpr.CreatePredefined(awaiter_definition.IsCompleted, loc); pe.InstanceExpression = fe_awaiter; completed_expr = pe; } completed_expr.EmitBranchable(ec, skip_continuation, true); } base.DoEmit(ec); // // The stack has to be empty before calling await continuation. We handle this // by lifting values which would be left on stack into class fields. The process // is quite complicated and quite hard to test because any expression can possibly // leave a value on the stack. // // Following assert fails when some of expression called before is missing EmitToField // or parent expression fails to find await in children expressions // ec.AssertEmptyStack(); var storey = (AsyncTaskStorey)machine_initializer.Storey; if (IsDynamic) { storey.EmitAwaitOnCompletedDynamic(ec, fe_awaiter); } else { storey.EmitAwaitOnCompleted(ec, fe_awaiter); } // Return ok machine_initializer.EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); ec.MarkLabel(skip_continuation); }
protected override bool DoDefineMembers() { TypeSpec bt; bool has_task_return_type = false; var istate_machine = Module.PredefinedTypes.IAsyncStateMachine; MethodSpec set_statemachine; if (return_type.IsCustomTaskType()) { // // TODO: Would be nice to cache all this on per-type basis // var btypes = Compiler.BuiltinTypes; bt = return_type.MemberDefinition.GetAsyncMethodBuilder(); TypeSpec bt_inflated; if (return_type.IsGeneric) { bt_inflated = bt.MakeGenericType(Module, bt.MemberDefinition.TypeParameters); } else { bt_inflated = bt; } var set_result_sign = MemberFilter.Method("SetResult", 0, ParametersCompiled.CreateFullyResolved(bt.MemberDefinition.TypeParameters), btypes.Void); set_result = new PredefinedMember <MethodSpec> (Module, bt, set_result_sign).Resolve(Location); var set_exception_sign = MemberFilter.Method("SetException", 0, ParametersCompiled.CreateFullyResolved(btypes.Exception), btypes.Void); set_exception = new PredefinedMember <MethodSpec> (Module, bt, set_exception_sign).Resolve(Location); var builder_factory_sign = MemberFilter.Method("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, bt_inflated); builder_factory = new PredefinedMember <MethodSpec> (Module, bt, builder_factory_sign).Resolve(Location); if (builder_factory?.IsStatic == false) { throw new NotImplementedException("report better error message"); } var builder_start_sign = MemberFilter.Method("Start", 1, new ParametersImported( new [] { new ParameterData(null, Parameter.Modifier.REF), }, new [] { new TypeParameterSpec(0, null, SpecialConstraint.None, Variance.None, null), }, false), btypes.Void); builder_start = new PredefinedMember <MethodSpec> (Module, bt, builder_start_sign).Resolve(Location); if (!istate_machine.Define()) { return(false); } var set_statemachine_sign = MemberFilter.Method("SetStateMachine", 0, ParametersCompiled.CreateFullyResolved(istate_machine.TypeSpec), btypes.Void); set_statemachine = new PredefinedMember <MethodSpec> (Module, bt, set_statemachine_sign).Resolve(Location);; var task_sign = MemberFilter.Property("Task", return_type.MemberDefinition as TypeSpec); task = new PredefinedMember <PropertySpec> (Module, bt, task_sign).Resolve(Location); if (set_result == null || set_exception == null || builder_factory == null || builder_start == null || set_statemachine == null || task == null || !Module.PredefinedTypes.INotifyCompletion.Define()) { return(false); } has_task_return_type = return_type.IsGeneric; } else { PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> bs; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; PredefinedMember <MethodSpec> sm; var pred_members = Module.PredefinedMembers; if (return_type.Kind == MemberKind.Void) { builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; bf = pred_members.AsyncVoidMethodBuilderCreate; bs = pred_members.AsyncVoidMethodBuilderStart; sr = pred_members.AsyncVoidMethodBuilderSetResult; se = pred_members.AsyncVoidMethodBuilderSetException; sm = pred_members.AsyncVoidMethodBuilderSetStateMachine; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; bs = pred_members.AsyncTaskMethodBuilderStart; sr = pred_members.AsyncTaskMethodBuilderSetResult; se = pred_members.AsyncTaskMethodBuilderSetException; sm = pred_members.AsyncTaskMethodBuilderSetStateMachine; task = pred_members.AsyncTaskMethodBuilderTask.Get(); } else { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; bf = pred_members.AsyncTaskMethodBuilderGenericCreate; bs = pred_members.AsyncTaskMethodBuilderGenericStart; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; se = pred_members.AsyncTaskMethodBuilderGenericSetException; sm = pred_members.AsyncTaskMethodBuilderGenericSetStateMachine; task = pred_members.AsyncTaskMethodBuilderGenericTask.Get(); has_task_return_type = true; } set_result = sr.Get(); set_exception = se.Get(); builder_factory = bf.Get(); builder_start = bs.Get(); set_statemachine = sm.Get(); if (!builder_type.Define() || !istate_machine.Define() || set_result == null || builder_factory == null || set_exception == null || set_statemachine == null || builder_start == null || !Module.PredefinedTypes.INotifyCompletion.Define()) { Report.Error(1993, Location, "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); return(base.DoDefineMembers()); } bt = builder_type.TypeSpec; } // // Inflate generic Task types // if (has_task_return_type) { var task_return_type = return_type.TypeArguments; if (mutator != null) { task_return_type = mutator.Mutate(task_return_type); } bt = bt.MakeGenericType(Module, task_return_type); set_result = MemberCache.GetMember(bt, set_result); set_exception = MemberCache.GetMember(bt, set_exception); set_statemachine = MemberCache.GetMember(bt, set_statemachine); if (task != null) { task = MemberCache.GetMember(bt, task); } } builder = AddCompilerGeneratedField("$builder", new TypeExpression(bt, Location)); Field rfield; if (has_task_return_type && HasAwaitInsideFinally) { // // Special case async block with return value from finally clause. In such case // we rewrite all return expresison stores to stfld to $return. Instead of treating // returns outside of finally and inside of finally differently. // rfield = AddCompilerGeneratedField("$return", new TypeExpression(bt.TypeArguments [0], Location)); } else { rfield = null; } var set_state_machine = new Method(this, new TypeExpression(Compiler.BuiltinTypes.Void, Location), Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC, new MemberName("SetStateMachine"), ParametersCompiled.CreateFullyResolved( new Parameter(new TypeExpression(istate_machine.TypeSpec, Location), "stateMachine", Parameter.Modifier.NONE, null, Location), istate_machine.TypeSpec), null); ToplevelBlock block = new ToplevelBlock(Compiler, set_state_machine.ParameterInfo, Location); block.IsCompilerGenerated = true; set_state_machine.Block = block; Members.Add(set_state_machine); if (!base.DoDefineMembers()) { return(false); } // // Fabricates SetStateMachine method // // public void SetStateMachine (IAsyncStateMachine stateMachine) // { // $builder.SetStateMachine (stateMachine); // } // var mg = MethodGroupExpr.CreatePredefined(set_statemachine, bt, Location); mg.InstanceExpression = new FieldExpr(builder, Location); var param_reference = block.GetParameterReference(0, Location); param_reference.Type = istate_machine.TypeSpec; param_reference.eclass = ExprClass.Variable; var args = new Arguments(1); args.Add(new Argument(param_reference)); set_state_machine.Block.AddStatement(new StatementExpression(new Invocation(mg, args))); if (has_task_return_type) { if (rfield != null) { HoistedReturnValue = new FieldExpr(rfield, Location) { InstanceExpression = new CompilerGeneratedThis(CurrentType, Location.Null) }; } else { HoistedReturnValue = TemporaryVariableReference.Create(bt.TypeArguments [0], StateMachineMethod.Block, Location); } } return(true); }
protected override Expression DoResolve(ResolveContext ec) { if (ec.Target == Target.JavaScript) { type = ec.BuiltinTypes.Dynamic; eclass = ExprClass.Value; return(this); } if (Expr is ElementAccess) { var elem_access = Expr as ElementAccess; if (elem_access.Arguments.Count != 1) { ec.Report.Error(7021, loc, "delete statement must have only one index argument."); return(null); } var expr = elem_access.Expr.Resolve(ec); if (expr.Type == null) { return(null); } if (expr.Type.IsArray) { ec.Report.Error(7021, loc, "delete statement not allowed on arrays."); return(null); } if (ec.Target == Target.JavaScript) { Expr = Expr.Resolve(ec); return(this); } if (!expr.Type.IsAsDynamicClass && (expr.Type.BuiltinType != BuiltinTypeSpec.Type.Dynamic)) { ec.Report.Error(7021, loc, "delete statement only allowed on dynamic types or dynamic classes"); return(null); } // cast expression to IDynamicClass and invoke __DeleteDynamicValue var dynClass = new Cast(new MemberAccess(new SimpleName("PlayScript", loc), "IDynamicClass", loc), expr, loc); removeExpr = new Invocation(new MemberAccess(dynClass, "__DeleteDynamicValue", loc), elem_access.Arguments); return(removeExpr.Resolve(ec)); } else if (Expr is MemberAccess) { if (ec.Target == Target.JavaScript) { Expr = Expr.Resolve(ec); return(this); } var memb_access = Expr as MemberAccess; var expr = memb_access.LeftExpression.Resolve(ec); if (expr.Type == null) { return(null); } if (!expr.Type.IsAsDynamicClass && (expr.Type.BuiltinType != BuiltinTypeSpec.Type.Dynamic)) { ec.Report.Error(7021, loc, "delete statement only allowed on dynamic types or dynamic classes"); return(null); } // cast expression to IDynamicClass and invoke __DeleteDynamicValue var dynClass = new Cast(new MemberAccess(new SimpleName("PlayScript", loc), "IDynamicClass", loc), expr, loc); var args = new Arguments(1); args.Add(new Argument(new StringLiteral(ec.BuiltinTypes, memb_access.Name, loc))); removeExpr = new Invocation(new MemberAccess(dynClass, "__DeleteDynamicValue", loc), args); return(removeExpr.Resolve(ec)); } else { // Error is reported elsewhere. return(null); } }
public void EmitPrologue(EmitContext ec) { var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); // // awaiter = expr.GetAwaiter (); // fe_awaiter.EmitAssign(ec, expr, false, false); Label skip_continuation = ec.DefineLabel(); is_completed.InstanceExpression = fe_awaiter; is_completed.EmitBranchable(ec, skip_continuation, true); base.DoEmit(ec); FieldSpec[] stack_fields = null; TypeSpec[] stack = null; // // Here is the clever bit. We know that await statement has to yield the control // back but it can appear inside almost any expression. This means the stack can // contain any depth of values and same values have to be present when the continuation // handles control back. // // For example: await a + await b // // In this case we fabricate a static stack forwarding method which moves the values // from the stack to async storey fields. On re-entry point we restore exactly same // stack using these fields. // // We fabricate a static method because we don't want to touch original stack and // the instance method would require `this' as the first stack value on the stack // if (ec.StackHeight > 0) { var async_storey = (AsyncTaskStorey)machine_initializer.Storey; stack = ec.GetStackTypes(); var method = async_storey.GetStackForwarder(stack, out stack_fields); ec.EmitThis(); ec.Emit(OpCodes.Call, method); } var mg_completed = MethodGroupExpr.CreatePredefined(on_completed, fe_awaiter.Type, loc); mg_completed.InstanceExpression = fe_awaiter; var args = new Arguments(1); var storey = (AsyncTaskStorey)machine_initializer.Storey; var fe_cont = new FieldExpr(storey.Continuation, loc); fe_cont.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); args.Add(new Argument(fe_cont)); // // awaiter.OnCompleted (continuation); // mg_completed.EmitCall(ec, args); // Return ok machine_initializer.EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); if (stack_fields != null) { for (int i = 0; i < stack_fields.Length; ++i) { ec.EmitThis(); var field = stack_fields[i]; // // We don't store `this' because it can be easily re-created // if (field == null) { continue; } if (stack[i] is ReferenceContainer) { ec.Emit(OpCodes.Ldflda, field); } else { ec.Emit(OpCodes.Ldfld, field); } } } ec.MarkLabel(skip_continuation); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments (3); flags |= ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; binder_args.Add (new Argument (new BinderFlags (flags, this))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); return new Invocation (GetBinder ("Convert", loc), binder_args); }
protected void EmitCall(EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { // // This method generates all internal infrastructure for a dynamic call. The // reason why it's quite complicated is the mixture of dynamic and anonymous // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous // methods can generate temporary storey as well (AnonStorey). Handling MVAR // type parameters rewrite is non-trivial in such case as there are various // combinations possible therefore the mutator is not straightforward. Secondly // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit // correct Site field type and its access from EmitContext. // int dyn_args_count = arguments == null ? 0 : arguments.Count; int default_args = isStatement ? 1 : 2; var module = ec.Module; bool has_ref_out_argument = false; var targs = new TypeExpression[dyn_args_count + default_args]; targs[0] = new TypeExpression(module.PredefinedTypes.CallSite.TypeSpec, loc); TypeExpression[] targs_for_instance = null; TypeParameterMutator mutator; var site_container = ec.CreateDynamicSite(); if (context_mvars != null) { TypeParameters tparam; TypeContainer sc = site_container; do { tparam = sc.CurrentTypeParameters; sc = sc.Parent; } while (tparam == null); mutator = new TypeParameterMutator(context_mvars, tparam); if (!ec.IsAnonymousStoreyMutateRequired) { targs_for_instance = new TypeExpression[targs.Length]; targs_for_instance[0] = targs[0]; } } else { mutator = null; } for (int i = 0; i < dyn_args_count; ++i) { Argument a = arguments[i]; if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) { has_ref_out_argument = true; } var t = a.Type; // Convert any internal type like dynamic or null to object if (t.Kind == MemberKind.InternalCompilerType) { t = ec.BuiltinTypes.Object; } if (targs_for_instance != null) { targs_for_instance[i + 1] = new TypeExpression(t, loc); } if (mutator != null) { t = t.Mutate(mutator); } targs[i + 1] = new TypeExpression(t, loc); } TypeExpr del_type = null; TypeExpr del_type_instance_access = null; if (!has_ref_out_argument) { string d_name = isStatement ? "Action" : "Func"; TypeSpec te = null; Namespace type_ns = module.GlobalRootNamespace.GetNamespace("System", true); if (type_ns != null) { te = type_ns.LookupType(module, d_name, dyn_args_count + default_args, LookupMode.IgnoreAccessibility, loc); } if (te != null) { if (!isStatement) { var t = type; if (t.Kind == MemberKind.InternalCompilerType) { t = ec.BuiltinTypes.Object; } if (targs_for_instance != null) { targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression(t, loc); } if (mutator != null) { t = t.Mutate(mutator); } targs[targs.Length - 1] = new TypeExpression(t, loc); } del_type = new GenericTypeExpr(te, new TypeArguments(targs), loc); if (targs_for_instance != null) { del_type_instance_access = new GenericTypeExpr(te, new TypeArguments(targs_for_instance), loc); } else { del_type_instance_access = del_type; } } } // // Create custom delegate when no appropriate predefined delegate has been found // Delegate d; if (del_type == null) { TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type; Parameter[] p = new Parameter[dyn_args_count + 1]; p[0] = new Parameter(targs[0], "p0", Parameter.Modifier.NONE, null, loc); var site = ec.CreateDynamicSite(); int index = site.Containers == null ? 0 : site.Containers.Count; if (mutator != null) { rt = mutator.Mutate(rt); } for (int i = 1; i < dyn_args_count + 1; ++i) { p[i] = new Parameter(targs[i], "p" + i.ToString("X"), arguments[i - 1].Modifier, null, loc); } d = new Delegate(site, new TypeExpression(rt, loc), Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, new MemberName("Container" + index.ToString("X")), new ParametersCompiled(p), null); d.CreateContainer(); d.DefineContainer(); d.Define(); d.PrepareEmit(); site.AddTypeContainer(d); // // Add new container to inflated site container when the // member cache already exists // if (site.CurrentType is InflatedTypeSpec && index > 0) { site.CurrentType.MemberCache.AddMember(d.CurrentType); } del_type = new TypeExpression(d.CurrentType, loc); if (targs_for_instance != null) { del_type_instance_access = null; } else { del_type_instance_access = del_type; } } else { d = null; } var site_type_decl = new GenericTypeExpr(module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments(del_type), loc); var field = site_container.CreateCallSiteField(site_type_decl, loc); if (field == null) { return; } if (del_type_instance_access == null) { var dt = d.CurrentType.DeclaringType.MakeGenericType(module, context_mvars.Types); del_type_instance_access = new TypeExpression(MemberCache.GetMember(dt, d.CurrentType), loc); } var instanceAccessExprType = new GenericTypeExpr(module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments(del_type_instance_access), loc); if (instanceAccessExprType.ResolveAsType(ec.MemberContext) == null) { return; } bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired; TypeSpec gt; if (inflate_using_mvar || context_mvars == null) { gt = site_container.CurrentType; } else { gt = site_container.CurrentType.MakeGenericType(module, context_mvars.Types); } // When site container already exists the inflated version has to be // updated manually to contain newly created field if (gt is InflatedTypeSpec && site_container.AnonymousMethodsCounter > 1) { var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes; var inflator = new TypeParameterInflator(module, gt, tparams, gt.TypeArguments); gt.MemberCache.AddMember(field.InflateMember(inflator)); } FieldExpr site_field_expr = new FieldExpr(MemberCache.GetMember(gt, field), loc); BlockContext bc = new BlockContext(ec.MemberContext, null, ec.BuiltinTypes.Void); Arguments args = new Arguments(1); args.Add(new Argument(binder)); StatementExpression s = new StatementExpression(new SimpleAssign(site_field_expr, new Invocation(new MemberAccess(instanceAccessExprType, "Create"), args))); using (ec.With(BuilderContext.Options.OmitDebugInfo, true)) { var conditionalAccessReceiver = IsConditionalAccessReceiver; var ca = ec.ConditionalAccess; if (conditionalAccessReceiver) { ec.ConditionalAccess = new ConditionalAccessContext(type, ec.DefineLabel()) { Statement = isStatement }; // // Emit conditional access expressions before dynamic call // is initialized. It pushes site_field_expr on stack before // the actual instance argument is emited which would cause // jump from non-empty stack. // EmitConditionalAccess(ec); } if (s.Resolve(bc)) { Statement init = new If(new Binary(Binary.Operator.Equality, site_field_expr, new NullLiteral(loc)), s, loc); init.Emit(ec); } args = new Arguments(1 + dyn_args_count); args.Add(new Argument(site_field_expr)); if (arguments != null) { int arg_pos = 1; foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add(new Argument(a.Expr, a.ArgType)); } else { args.Add(a); } if (inflate_using_mvar && a.Type != targs[arg_pos].Type) { a.Expr.Type = targs[arg_pos].Type; } ++arg_pos; } } var target = new DelegateInvocation(new MemberAccess(site_field_expr, "Target", loc).Resolve(bc), args, false, loc).Resolve(bc); if (target != null) { target.Emit(ec); } if (conditionalAccessReceiver) { ec.CloseConditionalAccess(!isStatement && type.IsNullableType ? type : null); ec.ConditionalAccess = ca; } } }
protected void EmitCall(EmitContext ec, Expression binder, Arguments arguments, bool isStatement) { int dyn_args_count = arguments == null ? 0 : arguments.Count; TypeExpr site_type = CreateSiteType (RootContext.ToplevelTypes.Compiler, arguments, dyn_args_count, isStatement); FieldExpr site_field_expr = new FieldExpr (CreateSiteField (site_type), loc); SymbolWriter.OpenCompilerGeneratedBlock (ec); Arguments args = new Arguments (1); args.Add (new Argument (binder)); StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (site_type, "Create"), args))); BlockContext bc = new BlockContext (ec.MemberContext, null, TypeManager.void_type); if (s.Resolve (bc)) { Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc), loc), s, loc); init.Emit (ec); } args = new Arguments (1 + dyn_args_count); args.Add (new Argument (site_field_expr)); if (arguments != null) { foreach (Argument a in arguments) { if (a is NamedArgument) { // Name is not valid in this context args.Add (new Argument (a.Expr, a.ArgType)); continue; } args.Add (a); } } Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); if (target != null) target.Emit (ec); SymbolWriter.CloseCompilerGeneratedBlock (ec); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments(member != null ? 5 : 3); bool is_member_access = member is MemberAccess; CSharpBinderFlags call_flags; if (!is_member_access && member is SimpleName) { call_flags = CSharpBinderFlags.InvokeSimpleName; is_member_access = true; } else { call_flags = 0; } binder_args.Add(new Argument(new BinderFlags(call_flags, this))); if (is_member_access) { binder_args.Add(new Argument(new StringLiteral(ec.BuiltinTypes, member.Name, member.Location))); } if (member != null && member.HasTypeArguments) { TypeArguments ta = member.TypeArguments; if (ta.Resolve(ec, false)) { var targs = new ArrayInitializer(ta.Count, loc); foreach (TypeSpec t in ta.Arguments) { targs.Add(new TypeOf(t, loc)); } binder_args.Add(new Argument(new ImplicitlyTypedArrayCreation(targs, loc))); } } else if (is_member_access) { binder_args.Add(new Argument(new NullLiteral(loc))); } binder_args.Add(new Argument(new TypeOf(ec.CurrentType, loc))); Expression real_args; if (args == null) { // Cannot be null because .NET trips over real_args = new ArrayCreation( new MemberAccess(GetBinderNamespace(loc), "CSharpArgumentInfo", loc), new ArrayInitializer(0, loc), loc); } else { real_args = new ImplicitlyTypedArrayCreation(args.CreateDynamicBinderArguments(ec), loc); } binder_args.Add(new Argument(real_args)); return(new Invocation(GetBinder(is_member_access ? "InvokeMember" : "Invoke", loc), binder_args)); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments (4); MemberAccess sle = new MemberAccess (new MemberAccess ( new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); var flags = ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; binder_args.Add (new Argument (new BinderFlags (flags, this))); binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (GetBinder ("UnaryOperation", loc), binder_args); }
public ArrayInitializer CreateDynamicBinderArguments(ResolveContext rc) { Location loc = Location.Null; var all = new ArrayInitializer(args.Count, loc); MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace(rc, loc); foreach (Argument a in args) { Arguments dargs = new Arguments(2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral(rc.BuiltinTypes, 0, loc); if (a.Expr is Constant) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "Constant", loc)); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsRef", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsOut", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.DynamicTypeName) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsStaticType", loc)); } TypeSpec arg_type; if (rc.FileType == SourceFileType.PlayScript && a.Expr is ArrayInitializer || a.Expr is AsObjectInitializer) { if (a.Expr is ArrayInitializer) { arg_type = rc.Module.PredefinedTypes.AsArray.Resolve(); } else { arg_type = rc.Module.PredefinedTypes.AsExpandoObject.Resolve(); } } else { arg_type = a.Expr.Type; } if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { MethodGroupExpr mg = a.Expr as MethodGroupExpr; bool wasConverted = false; // In PlayScript, we try to implicity convert to dynamic, which handles conversions of method groups to delegates, and // anon methods to delegates. if (rc.FileType == SourceFileType.PlayScript && (mg != null || arg_type == InternalType.AnonymousMethod)) { var expr = Convert.ImplicitConversion(rc, a.Expr, rc.BuiltinTypes.Dynamic, loc); if (expr != null) { a.Expr = expr; arg_type = rc.BuiltinTypes.Dynamic; wasConverted = true; } } // Failed.. check the C# error if (!wasConverted) { if (mg != null) { rc.Report.Error(1976, a.Expr.Location, "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", mg.Name); } else if (arg_type == InternalType.AnonymousMethod) { rc.Report.Error(1977, a.Expr.Location, "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { rc.Report.Error(1978, a.Expr.Location, "An expression of type `{0}' cannot be used as an argument of dynamic operation", arg_type.GetSignatureForError()); } } info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "NamedArgument", loc)); named_value = na.Name; } else { named_value = null; } dargs.Add(new Argument(info_flags)); dargs.Add(new Argument(new StringLiteral(rc.BuiltinTypes, named_value, loc))); all.Add(new Invocation(new MemberAccess(new MemberAccess(binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); } return(all); }
public ArrayList CreateDynamicBinderArguments() { ArrayList all = new ArrayList(args.Count); Location loc = Location.Null; MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace(loc); foreach (Argument a in args) { Arguments dargs = new Arguments(2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral(0, loc); if (a.Expr is Constant) { // Any constant is emitted as a literal info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "LiteralConstant", loc)); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsRef", loc)); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsOut", loc)); } else if (a.ArgType == Argument.AType.DynamicStatic) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsStaticType", loc)); } if (!TypeManager.IsDynamicType(a.Expr.Type)) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "NamedArgument", loc)); named_value = na.Name.Value; } else { named_value = null; } dargs.Add(new Argument(info_flags)); dargs.Add(new Argument(new StringLiteral(named_value, loc))); all.Add(new New(new MemberAccess(binder, "CSharpArgumentInfo", loc), dargs, loc)); } return(all); }
public void EmitPrologue(EmitContext ec) { var fe_awaiter = new FieldExpr(awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); // // awaiter = expr.GetAwaiter (); // fe_awaiter.EmitAssign(ec, expr, false, false); Label skip_continuation = ec.DefineLabel(); Expression completed_expr; if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); Arguments dargs = new Arguments(1); dargs.Add(new Argument(fe_awaiter)); completed_expr = new DynamicMemberBinder("IsCompleted", dargs, loc).Resolve(rc); } else { var pe = PropertyExpr.CreatePredefined(is_completed, loc); pe.InstanceExpression = fe_awaiter; completed_expr = pe; } completed_expr.EmitBranchable(ec, skip_continuation, true); base.DoEmit(ec); // // The stack has to be empty before calling await continuation. We handle this // by lifting values which would be left on stack into class fields. The process // is quite complicated and quite hard to test because any expression can possibly // leave a value on the stack. // // Following assert fails when some of expression called before is missing EmitToField // or parent expression fails to find await in children expressions // ec.AssertEmptyStack(); var args = new Arguments(1); var storey = (AsyncTaskStorey)machine_initializer.Storey; var fe_cont = new FieldExpr(storey.Continuation, loc); fe_cont.InstanceExpression = new CompilerGeneratedThis(ec.CurrentType, loc); args.Add(new Argument(fe_cont)); if (IsDynamic) { var rc = new ResolveContext(ec.MemberContext); var mg_expr = new Invocation(new MemberAccess(fe_awaiter, "OnCompleted"), args).Resolve(rc); ExpressionStatement es = (ExpressionStatement)mg_expr; es.EmitStatement(ec); } else { var mg_completed = MethodGroupExpr.CreatePredefined(on_completed, fe_awaiter.Type, loc); mg_completed.InstanceExpression = fe_awaiter; // // awaiter.OnCompleted (continuation); // mg_completed.EmitCall(ec, args); } // Return ok machine_initializer.EmitLeave(ec, unwind_protect); ec.MarkLabel(resume_point); ec.MarkLabel(skip_continuation); }
protected override bool DoDefineMembers () { if (!base.DoDefineMembers ()) return false; Location loc = Location; var equals_parameters = ParametersCompiled.CreateFullyResolved ( new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object); Method equals = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), equals_parameters, null); equals_parameters[0].Resolve (equals, 0); Method tostring = new Method (this, new TypeExpression (Compiler.BuiltinTypes.String, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); TypeExpr current_type; if (CurrentTypeParameters != null) { var targs = new TypeArguments (); for (int i = 0; i < CurrentTypeParameters.Count; ++i) { targs.Add (new TypeParameterExpr (CurrentTypeParameters[i], Location)); } current_type = new GenericTypeExpr (Definition, targs, loc); } else { current_type = new TypeExpression (Definition, loc); } var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc); equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other)); var other_variable = new LocalVariableReference (li_other, loc); MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); Expression rs_equals = null; Expression string_concat = new StringConstant (Compiler.BuiltinTypes, "{", loc); Expression rs_hashcode = new IntConstant (Compiler.BuiltinTypes, -2128831035, loc); for (int i = 0; i < parameters.Count; ++i) { var p = parameters [i]; var f = (Field) Members [i * 2]; MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( system_collections_generic, "EqualityComparer", new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc), "Default", loc); Arguments arguments_equal = new Arguments (2); arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); Expression field_equal = new Invocation (new MemberAccess (equality_comparer, "Equals", loc), arguments_equal); Arguments arguments_hashcode = new Arguments (1); arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, "GetHashCode", loc), arguments_hashcode); IntConstant FNV_prime = new IntConstant (Compiler.BuiltinTypes, 16777619, loc); rs_hashcode = new Binary (Binary.Operator.Multiply, new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode), FNV_prime); Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality, new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc))), new Invocation (new MemberAccess ( new MemberAccess (new This (f.Location), f.Name), "ToString"), null), new StringConstant (Compiler.BuiltinTypes, string.Empty, loc), loc); if (rs_equals == null) { rs_equals = field_equal; string_concat = new Binary (Binary.Operator.Addition, string_concat, new Binary (Binary.Operator.Addition, new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc), field_to_string)); continue; } // // Implementation of ToString () body using string concatenation // string_concat = new Binary (Binary.Operator.Addition, new Binary (Binary.Operator.Addition, string_concat, new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc)), field_to_string); rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal); } string_concat = new Binary (Binary.Operator.Addition, string_concat, new StringConstant (Compiler.BuiltinTypes, " }", loc)); // // Equals (object obj) override // var other_variable_assign = new TemporaryVariableReference (li_other, loc); equals_block.AddStatement (new StatementExpression ( new SimpleAssign (other_variable_assign, new As (equals_block.GetParameterReference (0, loc), current_type, loc), loc))); Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc)); if (rs_equals != null) equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals); equals_block.AddStatement (new Return (equals_test, loc)); equals.Block = equals_block; equals.Define (); Members.Add (equals); // // GetHashCode () override // Method hashcode = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Int, loc), Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("GetHashCode", loc), Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); // // Modified FNV with good avalanche behavior and uniform // distribution with larger hash sizes. // // const int FNV_prime = 16777619; // int hash = (int) 2166136261; // foreach (int d in data) // hash = (hash ^ d) * FNV_prime; // hash += hash << 13; // hash ^= hash >> 7; // hash += hash << 3; // hash ^= hash >> 17; // hash += hash << 5; ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc); Block hashcode_block = new Block (hashcode_top, loc, loc); hashcode_top.AddStatement (new Unchecked (hashcode_block, loc)); var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc); hashcode_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_hash.Type, loc), li_hash)); LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc); hashcode_block.AddStatement (new StatementExpression ( new SimpleAssign (hash_variable_assign, rs_hashcode))); var hash_variable = new LocalVariableReference (li_hash, loc); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc))))); hashcode_block.AddStatement (new StatementExpression ( new CompoundAssign (Binary.Operator.Addition, hash_variable, new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc))))); hashcode_block.AddStatement (new Return (hash_variable, loc)); hashcode.Block = hashcode_top; hashcode.Define (); Members.Add (hashcode); // // ToString () override // ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); tostring_block.AddStatement (new Return (string_concat, loc)); tostring.Block = tostring_block; tostring.Define (); Members.Add (tostring); return true; }
protected override bool DoDefineMembers() { var action = Module.PredefinedTypes.Action.Resolve(); if (action != null) { continuation = AddCompilerGeneratedField("$continuation", new TypeExpression(action, Location), true); continuation.ModFlags |= Modifiers.READONLY; } PredefinedType builder_type; PredefinedMember <MethodSpec> bf; PredefinedMember <MethodSpec> sr; PredefinedMember <MethodSpec> se; bool has_task_return_type = false; var pred_members = Module.PredefinedMembers; if (return_type.Kind == MemberKind.Void) { builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; bf = pred_members.AsyncVoidMethodBuilderCreate; sr = pred_members.AsyncVoidMethodBuilderSetResult; se = pred_members.AsyncVoidMethodBuilderSetException; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; sr = pred_members.AsyncTaskMethodBuilderSetResult; se = pred_members.AsyncTaskMethodBuilderSetException; task = pred_members.AsyncTaskMethodBuilderTask.Get(); } else { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; bf = pred_members.AsyncTaskMethodBuilderGenericCreate; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; se = pred_members.AsyncTaskMethodBuilderGenericSetException; task = pred_members.AsyncTaskMethodBuilderGenericTask.Get(); has_task_return_type = true; } set_result = sr.Get(); set_exception = se.Get(); var builder_factory = bf.Get(); if (!builder_type.Define() || set_result == null || builder_factory == null || set_exception == null) { Report.Error(1993, Location, "Cannot find compiler required types for asynchronous functions support. Are you targeting the wrong framework version?"); return(base.DoDefineMembers()); } var bt = builder_type.TypeSpec; // // Inflate generic Task types // if (has_task_return_type) { var task_return_type = return_type.TypeArguments; if (mutator != null) { task_return_type = mutator.Mutate(task_return_type); } bt = bt.MakeGenericType(Module, task_return_type); builder_factory = MemberCache.GetMember <MethodSpec> (bt, builder_factory); set_result = MemberCache.GetMember <MethodSpec> (bt, set_result); set_exception = MemberCache.GetMember <MethodSpec> (bt, set_exception); if (task != null) { task = MemberCache.GetMember <PropertySpec> (bt, task); } } builder = AddCompilerGeneratedField("$builder", new TypeExpression(bt, Location)); if (!base.DoDefineMembers()) { return(false); } MethodGroupExpr mg; var block = instance_constructors[0].Block; // // Initialize continuation with state machine method // if (continuation != null) { var args = new Arguments(1); mg = MethodGroupExpr.CreatePredefined(StateMachineMethod.Spec, spec, Location); args.Add(new Argument(mg)); block.AddStatement( new StatementExpression(new SimpleAssign( new FieldExpr(continuation, Location), new NewDelegate(action, args, Location), Location ))); } mg = MethodGroupExpr.CreatePredefined(builder_factory, bt, Location); block.AddStatement( new StatementExpression(new SimpleAssign( new FieldExpr(builder, Location), new Invocation(mg, new Arguments(0)), Location))); if (has_task_return_type) { hoisted_return = LocalVariable.CreateCompilerGenerated(bt.TypeArguments[0], block, Location); } return(true); }
public static Arguments CreateDelegateMethodArguments (ResolveContext rc, AParametersCollection pd, TypeSpec[] types, Location loc) { Arguments delegate_arguments = new Arguments (pd.Count); for (int i = 0; i < pd.Count; ++i) { Argument.AType atype_modifier; switch (pd.FixedParameters [i].ModFlags & Parameter.Modifier.RefOutMask) { case Parameter.Modifier.REF: atype_modifier = Argument.AType.Ref; break; case Parameter.Modifier.OUT: atype_modifier = Argument.AType.Out; break; default: atype_modifier = 0; break; } var ptype = types[i]; if (ptype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) ptype = rc.BuiltinTypes.Object; delegate_arguments.Add (new Argument (new TypeExpression (ptype, loc), atype_modifier)); } return delegate_arguments; }
public void Resolve() { if (Compiler.Settings.Unsafe && module.PredefinedTypes.SecurityAction.Define()) { // // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] // when -unsafe option was specified // Location loc = Location.Null; MemberAccess system_security_permissions = new MemberAccess(new MemberAccess( new QualifiedAliasMember(QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); var req_min = module.PredefinedMembers.SecurityActionRequestMinimum.Resolve(loc); Arguments pos = new Arguments(1); pos.Add(new Argument(req_min.GetConstant(null))); Arguments named = new Arguments(1); named.Add(new NamedArgument("SkipVerification", loc, new BoolLiteral(Compiler.BuiltinTypes, true, loc))); Attribute g = new Attribute("assembly", new MemberAccess(system_security_permissions, "SecurityPermissionAttribute"), new Arguments[] { pos, named }, loc, false); g.AttachTo(module, module); // Disable no-location warnings (e.g. obsolete) for compiler generated attribute Compiler.Report.DisableReporting(); try { var ctor = g.Resolve(); if (ctor != null) { g.ExtractSecurityPermissionSet(ctor, ref declarative_security); } } finally { Compiler.Report.EnableReporting(); } } if (module.OptAttributes == null) { return; } // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types. if (!module.OptAttributes.CheckTargets()) { return; } cls_attribute = module.ResolveAssemblyAttribute(module.PredefinedAttributes.CLSCompliant); if (cls_attribute != null) { is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue(); } if (added_modules != null && Compiler.Settings.VerifyClsCompliance && is_cls_compliant) { foreach (var m in added_modules) { if (!m.IsCLSCompliant) { Report.Error(3013, "Added modules must be marked with the CLSCompliant attribute to match the assembly", m.Name); } } } Attribute a = module.ResolveAssemblyAttribute(module.PredefinedAttributes.RuntimeCompatibility); if (a != null) { var val = a.GetNamedValue("WrapNonExceptionThrows") as BoolConstant; if (val != null) { wrap_non_exception_throws = val.Value; } } }
public ArrayInitializer CreateDynamicBinderArguments (ResolveContext rc) { Location loc = Location.Null; var all = new ArrayInitializer (args.Count, loc); MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc); foreach (Argument a in args) { Arguments dargs = new Arguments (2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral (0, loc); var constant = a.Expr as Constant; if (constant != null && constant.IsLiteral) { info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "Constant", loc), loc); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsRef", loc), loc); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsOut", loc), loc); } else if (a.ArgType == Argument.AType.DynamicTypeName) { info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsStaticType", loc), loc); } var arg_type = a.Expr.Type; if (arg_type != InternalType.Dynamic) { MethodGroupExpr mg = a.Expr as MethodGroupExpr; if (mg != null) { rc.Report.Error (1976, a.Expr.Location, "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", mg.Name); } else if (arg_type == InternalType.AnonymousMethod) { rc.Report.Error (1977, a.Expr.Location, "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); } else if (arg_type == TypeManager.void_type || arg_type == InternalType.Arglist || arg_type.IsPointer) { rc.Report.Error (1978, a.Expr.Location, "An expression of type `{0}' cannot be used as an argument of dynamic operation", TypeManager.CSharpName (arg_type)); } info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "NamedArgument", loc), loc); named_value = na.Name; } else { named_value = null; } dargs.Add (new Argument (info_flags)); dargs.Add (new Argument (new StringLiteral (named_value, loc))); all.Add (new Invocation (new MemberAccess (new MemberAccess (binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); } return all; }
Method GenerateNumberMatcher() { var loc = Location; var parameters = ParametersCompiled.CreateFullyResolved( new [] { new Parameter(new TypeExpression(Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), new Parameter(new TypeExpression(Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc), new Parameter(new TypeExpression(Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc), }, new [] { Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Object, Compiler.BuiltinTypes.Bool }); var m = new Method(this, new TypeExpression(Compiler.BuiltinTypes.Bool, loc), Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName("NumberMatcher", loc), parameters, null); parameters [0].Resolve(m, 0); parameters [1].Resolve(m, 1); parameters [2].Resolve(m, 2); ToplevelBlock top_block = new ToplevelBlock(Compiler, parameters, loc); m.Block = top_block; // // if (enumType) // return Equals (obj, value); // var equals_args = new Arguments(2); equals_args.Add(new Argument(top_block.GetParameterReference(0, loc))); equals_args.Add(new Argument(top_block.GetParameterReference(1, loc))); var if_type = new If( top_block.GetParameterReference(2, loc), new Return(new Invocation(new SimpleName("Equals", loc), equals_args), loc), loc); top_block.AddStatement(if_type); // // if (obj is Enum || obj == null) // return false; // var if_enum = new If( new Binary(Binary.Operator.LogicalOr, new Is(top_block.GetParameterReference(0, loc), new TypeExpression(Compiler.BuiltinTypes.Enum, loc), loc), new Binary(Binary.Operator.Equality, top_block.GetParameterReference(0, loc), new NullLiteral(loc))), new Return(new BoolLiteral(Compiler.BuiltinTypes, false, loc), loc), loc); top_block.AddStatement(if_enum); var system_convert = new MemberAccess(new QualifiedAliasMember("global", "System", loc), "Convert", loc); var expl_block = new ExplicitBlock(top_block, loc, loc); // // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value)); // var lv_converted = LocalVariable.CreateCompilerGenerated(Compiler.BuiltinTypes.Object, top_block, loc); var arguments_gettypecode = new Arguments(1); arguments_gettypecode.Add(new Argument(top_block.GetParameterReference(1, loc))); var gettypecode = new Invocation(new MemberAccess(system_convert, "GetTypeCode", loc), arguments_gettypecode); var arguments_changetype = new Arguments(1); arguments_changetype.Add(new Argument(top_block.GetParameterReference(0, loc))); arguments_changetype.Add(new Argument(gettypecode)); var changetype = new Invocation(new MemberAccess(system_convert, "ChangeType", loc), arguments_changetype); expl_block.AddStatement(new StatementExpression(new SimpleAssign(new LocalVariableReference(lv_converted, loc), changetype, loc))); // // return converted.Equals (value) // var equals_arguments = new Arguments(1); equals_arguments.Add(new Argument(top_block.GetParameterReference(1, loc))); var equals_invocation = new Invocation(new MemberAccess(new LocalVariableReference(lv_converted, loc), "Equals"), equals_arguments); expl_block.AddStatement(new Return(equals_invocation, loc)); var catch_block = new ExplicitBlock(top_block, loc, loc); catch_block.AddStatement(new Return(new BoolLiteral(Compiler.BuiltinTypes, false, loc), loc)); top_block.AddStatement(new TryCatch(expl_block, new List <Catch> () { new Catch(catch_block, loc) }, loc, false)); m.Define(); m.PrepareEmit(); AddMember(m); return(m); }
public Arguments Clone (CloneContext ctx) { Arguments cloned = new Arguments (args.Count); foreach (Argument a in args) cloned.Add (a.Clone (ctx)); return cloned; }
public ArrayInitializer CreateDynamicBinderArguments(ResolveContext rc) { Location loc = Location.Null; var all = new ArrayInitializer(args.Count, loc); MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace(loc); foreach (Argument a in args) { Arguments dargs = new Arguments(2); // CSharpArgumentInfoFlags.None = 0 const string info_flags_enum = "CSharpArgumentInfoFlags"; Expression info_flags = new IntLiteral(rc.BuiltinTypes, 0, loc); if (a.Expr is Constant) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "Constant", loc)); } else if (a.ArgType == Argument.AType.Ref) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsRef", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.Out) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsOut", loc)); info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } else if (a.ArgType == Argument.AType.DynamicTypeName) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "IsStaticType", loc)); } var arg_type = a.Expr.Type; if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { MethodGroupExpr mg = a.Expr as MethodGroupExpr; if (mg != null) { rc.Report.Error(1976, a.Expr.Location, "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", mg.Name); } else if (arg_type == InternalType.AnonymousMethod) { rc.Report.Error(1977, a.Expr.Location, "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { rc.Report.Error(1978, a.Expr.Location, "An expression of type `{0}' cannot be used as an argument of dynamic operation", arg_type.GetSignatureForError()); } info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "UseCompileTimeType", loc)); } string named_value; NamedArgument na = a as NamedArgument; if (na != null) { info_flags = new Binary(Binary.Operator.BitwiseOr, info_flags, new MemberAccess(new MemberAccess(binder, info_flags_enum, loc), "NamedArgument", loc)); named_value = na.Name; } else { named_value = null; } dargs.Add(new Argument(info_flags)); dargs.Add(new Argument(new StringLiteral(rc.BuiltinTypes, named_value, loc))); all.Add(new Invocation(new MemberAccess(new MemberAccess(binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); } return(all); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments (3); binder_args.Add (new Argument (new BinderFlags (0, this))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (GetBinder ("InvokeConstructor", loc), binder_args); }
protected override Expression ResolveConversions(ResolveContext ec) { // // LAMESPEC: Under dynamic context no target conversion is happening // This allows more natual dynamic behaviour but breaks compatibility // with static binding // if (target is RuntimeValueExpression) { return(this); } TypeSpec target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists(ec, source, target_type)) { source = Convert.ImplicitConversion(ec, source, target_type, loc); return(this); } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b == null) { if (source is ReducedExpression) { b = ((ReducedExpression)source).OriginalExpression as Binary; } else if (source is ReducedExpression.ReducedConstantExpression) { b = ((ReducedExpression.ReducedConstantExpression)source).OriginalExpression as Binary; } else if (source is Nullable.LiftedBinaryOperator) { var po = ((Nullable.LiftedBinaryOperator)source); if (po.UserOperator == null) { b = po.Binary; } } else if (source is TypeCast) { b = ((TypeCast)source).Child as Binary; } } if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists(ec, right, target_type)) { source = Convert.ExplicitConversion(ec, source, target_type, loc); return(this); } } if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { Arguments arg = new Arguments(1); arg.Add(new Argument(source)); return(new SimpleAssign(target, new DynamicConversion(target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve(ec)); } right.Error_ValueCannotBeConverted(ec, target_type, false); return(null); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments (3); binder_args.Add (new Argument (new BinderFlags (0, this))); binder_args.Add (new Argument (new StringLiteral (name, loc))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); return new Invocation (GetBinder ("IsEvent", loc), binder_args); }
protected override Expression DoResolve(ResolveContext ec) { right = right.Resolve(ec); if (right == null) { return(null); } MemberAccess ma = target as MemberAccess; using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve(ec); } if (target == null) { return(null); } if (target is MethodGroupExpr) { ec.Report.Error(1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return(null); } var event_expr = target as EventExpr; if (event_expr != null) { source = Convert.ImplicitConversionRequired(ec, right, target.Type, loc); if (source == null) { return(null); } Expression rside; if (op == Binary.Operator.Addition) { rside = EmptyExpression.EventAddition; } else if (op == Binary.Operator.Subtraction) { rside = EmptyExpression.EventSubtraction; } else { rside = null; } target = target.ResolveLValue(ec, rside); if (target == null) { return(null); } eclass = ExprClass.Value; type = event_expr.Operator.ReturnType; return(this); } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) { left = new TargetExpression(target); } source = new Binary(op, left, right, true); if (target is DynamicMemberAssignable) { Arguments targs = ((DynamicMemberAssignable)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(source)); var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; // // Compound assignment does target conversion using additional method // call, set checked context as the binary operation can overflow // if (ec.HasSet(ResolveContext.Options.CheckedScope)) { binder_flags |= CSharpBinderFlags.CheckedContext; } if (target is DynamicMemberBinder) { source = new DynamicMemberBinder(ma.Name, binder_flags, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(targs.Count + 1); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(targs.Count); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } } else { source = new DynamicIndexBinder(binder_flags, args, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments (member != null ? 5 : 3); bool is_member_access = member is MemberAccess; CSharpBinderFlags call_flags; if (!is_member_access && member is SimpleName) { call_flags = CSharpBinderFlags.InvokeSimpleName; is_member_access = true; } else { call_flags = 0; } binder_args.Add (new Argument (new BinderFlags (call_flags, this))); if (is_member_access) binder_args.Add (new Argument (new StringLiteral (member.Name, member.Location))); if (member != null && member.HasTypeArguments) { TypeArguments ta = member.TypeArguments; if (ta.Resolve (ec)) { var targs = new ArrayInitializer (ta.Count, loc); foreach (TypeSpec t in ta.Arguments) targs.Add (new TypeOf (new TypeExpression (t, loc), loc)); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", targs, loc))); } } else if (is_member_access) { binder_args.Add (new Argument (new NullLiteral (loc))); } binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); Expression real_args; if (args == null) { // Cannot be null because .NET trips over real_args = new ArrayCreation ( new MemberAccess (GetBinderNamespace (loc), "CSharpArgumentInfo", loc), "[]", new ArrayInitializer (0, loc), loc); } else { real_args = new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc); } binder_args.Add (new Argument (real_args)); return new Invocation (GetBinder (is_member_access ? "InvokeMember" : "Invoke", loc), binder_args); }
protected override Expression DoResolve(ResolveContext rc) { // BEN: This won't work because the returned type won't pass Mono's type checkers. // if (rc.Target == Target.JavaScript) { // this.type = rc.Module.PredefinedTypes.AsArray.Resolve(); // this.eclass = ExprClass.Value; // foreach (var elem in Elements) // elem.Resolve (rc); // return this; // } // Attempt to build simple const initializer bool is_const_init = false; TypeSpec const_type = null; if (elements.Count > 0) { is_const_init = true; const_type = vectorType != null?vectorType.ResolveAsType(rc) : null; foreach (var elem in elements) { if (elem == null) { is_const_init = false; break; } if (!(elem is Constant) && !(elem is Unary && ((Unary)elem).Expr is Constant)) { is_const_init = false; break; } TypeSpec elemType = elem.Type; if (vectorType == null) { if (elemType == null) { is_const_init = false; break; } if (const_type == null) { const_type = BuiltinTypeSpec.IsPrimitiveType(elemType) ? elemType : rc.BuiltinTypes.Object; } if (const_type != elemType) { if (((const_type == rc.BuiltinTypes.Int || const_type == rc.BuiltinTypes.UInt) && elemType == rc.BuiltinTypes.Double) || (const_type == rc.BuiltinTypes.Double && (elemType == rc.BuiltinTypes.Int || elemType == rc.BuiltinTypes.UInt))) { const_type = rc.BuiltinTypes.Double; } else { const_type = rc.BuiltinTypes.Object; } } } } } TypeExpression type; if (vectorType != null) // For new <Type> [ initializer ] expressions.. { var elemTypeSpec = vectorType.ResolveAsType(rc); if (elemTypeSpec != null) { type = new TypeExpression( rc.Module.PredefinedTypes.AsVector.Resolve().MakeGenericType(rc, new [] { elemTypeSpec }), Location); } else { type = new TypeExpression(rc.Module.PredefinedTypes.AsArray.Resolve(), Location); } } else { type = new TypeExpression(rc.Module.PredefinedTypes.AsArray.Resolve(), Location); } TypeSpec typeSpec = type.ResolveAsType(rc.MemberContext); if (typeSpec.IsArray) { ArrayCreation arrayCreate = (ArrayCreation) new ArrayCreation(type, this).Resolve(rc); return(arrayCreate); } else if (is_const_init) { // If all elements in the initializer list are simple constants, we just pass the elements in a .NET array to the // PS Array initializer. var newArgs = new Arguments(1); newArgs.Add(new Argument(new ArrayCreation(new TypeExpression(const_type, loc), this, loc))); return(new New(type, newArgs, loc).Resolve(rc)); } else { var initElems = new List <Expression>(); foreach (var e in elements) { initElems.Add(new CollectionElementInitializer(e)); } return(new NewInitialize(type, null, new CollectionOrObjectInitializers(initElems, Location), Location).Resolve(rc)); } }
protected override Expression CreateCallSiteBinder(ResolveContext ec, Arguments args, bool isSet) { Arguments binder_args = new Arguments (4); binder_args.Add (new Argument (new BinderFlags (0, this))); binder_args.Add (new Argument (new StringLiteral (name, loc))); binder_args.Add (new Argument (new TypeOf (new TypeExpression (ec.CurrentType, loc), loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation ("[]", args.CreateDynamicBinderArguments (ec), loc))); return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args); }
protected override Expression DoResolve (ResolveContext ec) { Expression clone = source.Clone (new CloneContext ()); clone = clone.Resolve (ec); if (clone == null) return null; // // A useful feature for the REPL: if we can resolve the expression // as a type, Describe the type; // if (ec.Module.Evaluator.DescribeTypeExpressions && !(ec.CurrentAnonymousMethod is AsyncInitializer)) { var old_printer = ec.Report.SetPrinter (new SessionReportPrinter ()); Expression tclone; try { // Note: clone context cannot be shared otherwise block mapping would leak tclone = source.Clone (new CloneContext ()); tclone = tclone.Resolve (ec, ResolveFlags.Type); if (ec.Report.Errors > 0) tclone = null; } finally { ec.Report.SetPrinter (old_printer); } if (tclone is TypeExpr) { Arguments args = new Arguments (1); args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location))); return new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec); } } // This means its really a statement. if (clone.Type.Kind == MemberKind.Void || clone is DynamicInvocation || clone is Assign) { return clone; } source = clone; var host = (Method) ec.MemberContext.CurrentMemberDefinition; if (host.ParameterInfo.IsEmpty) { eclass = ExprClass.Value; type = InternalType.FakeInternalType; return this; } target = new SimpleName (host.ParameterInfo[0].Name, Location); return base.DoResolve (ec); }
protected override Expression DoResolve (ResolveContext ec) { right = right.Resolve (ec); if (right == null) return null; MemberAccess ma = target as MemberAccess; using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve (ec); } if (target == null) return null; if (target is MethodGroupExpr){ ec.Report.Error (1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return null; } var event_expr = target as EventExpr; if (event_expr != null) { source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc); if (source == null) return null; Expression rside; if (op == Binary.Operator.Addition) rside = EmptyExpression.EventAddition; else if (op == Binary.Operator.Subtraction) rside = EmptyExpression.EventSubtraction; else rside = null; target = target.ResolveLValue (ec, rside); if (target == null) return null; eclass = ExprClass.Value; type = event_expr.Operator.ReturnType; return this; } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) left = new TargetExpression (target); source = new Binary (op, left, right, true); if (target is DynamicMemberAssignable) { Arguments targs = ((DynamicMemberAssignable) target).Arguments; source = source.Resolve (ec); Arguments args = new Arguments (targs.Count + 1); args.AddRange (targs); args.Add (new Argument (source)); var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; // // Compound assignment does target conversion using additional method // call, set checked context as the binary operation can overflow // if (ec.HasSet (ResolveContext.Options.CheckedScope)) binder_flags |= CSharpBinderFlags.CheckedContext; if (target is DynamicMemberBinder) { source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments (targs.Count + 1); args.AddRange (targs); args.Add (new Argument (right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; var invoke = DynamicInvocation.CreateSpecialNameInvoke ( new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec); args = new Arguments (targs.Count); args.AddRange (targs); source = new DynamicEventCompoundAssign (ma.Name, args, (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); } } else { source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec); } return source; } return base.DoResolve (ec); }
public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); args.Add (new Argument (this)); args.Add (new Argument (new TypeOf (type, loc))); return CreateExpressionFactoryCall (ec, "Constant", args); }
void FabricateBodyStatement () { // // Delegate obj1 = backing_field // do { // Delegate obj2 = obj1; // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); // } while ((object)obj1 != (object)obj2) // var field_info = ((EventField) method).backing_field; FieldExpr f_expr = new FieldExpr (field_info, Location); if (!IsStatic) f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj1, Location), Location), new Cast (new TypeExpression (Module.Compiler.BuiltinTypes.Object, Location), new LocalVariableReference (obj2, Location), Location))); var body = new ExplicitBlock (block, Location, Location); block.AddStatement (new Do (body, cond, Location, Location)); body.AddStatement (new StatementExpression ( new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); var args_oper = new Arguments (2); args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); args_oper.Add (new Argument (block.GetParameterReference (0, Location))); var op_method = GetOperation (Location); var args = new Arguments (3); args.Add (new Argument (f_expr, Argument.AType.Ref)); args.Add (new Argument (new Cast ( new TypeExpression (field_info.MemberType, Location), new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper), Location))); args.Add (new Argument (new LocalVariableReference (obj1, Location))); var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location); if (cas == null) return; body.AddStatement (new StatementExpression (new SimpleAssign ( new LocalVariableReference (obj1, Location), new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); }
public Expression CreateCallSiteBinder(ResolveContext ec, Arguments args) { Arguments binder_args = new Arguments(member != null ? 5 : 3); MemberAccess binder = GetBinderNamespace(loc); bool is_member_access = member is MemberAccess; string call_flags; if (!is_member_access && member is SimpleName) { call_flags = "SimpleNameCall"; is_member_access = true; } else { call_flags = "None"; } binder_args.Add(new Argument(new MemberAccess(new MemberAccess(binder, "CSharpCallFlags", loc), call_flags, loc))); if (is_member_access) { binder_args.Add(new Argument(new StringLiteral(member.Name, member.Location))); } binder_args.Add(new Argument(new TypeOf(new TypeExpression(ec.CurrentType, loc), loc))); if (member != null && member.HasTypeArguments) { TypeArguments ta = member.TypeArguments; if (ta.Resolve(ec)) { ArrayList targs = new ArrayList(ta.Count); foreach (Type t in ta.Arguments) { targs.Add(new TypeOf(new TypeExpression(t, loc), loc)); } binder_args.Add(new Argument(new ImplicitlyTypedArrayCreation("[]", targs, loc))); } } else if (is_member_access) { binder_args.Add(new Argument(new NullLiteral(loc))); } Expression real_args; if (args == null) { // Cannot be null because .NET trips over real_args = new ArrayCreation(new MemberAccess(binder, "CSharpArgumentInfo", loc), "[]", new ArrayList(0), loc); } else { real_args = new ImplicitlyTypedArrayCreation("[]", args.CreateDynamicBinderArguments(), loc); } binder_args.Add(new Argument(real_args)); return(new New(new MemberAccess(binder, is_member_access ? "CSharpInvokeMemberBinder" : "CSharpInvokeBinder", loc), binder_args, loc)); }
protected override Expression DoResolve (ResolveContext ec) { Expression clone = source.Clone (new CloneContext ()); clone = clone.Resolve (ec); if (clone == null) return null; // // A useful feature for the REPL: if we can resolve the expression // as a type, Describe the type; // if (ec.Module.Evaluator.DescribeTypeExpressions){ var old_printer = ec.Report.SetPrinter (new SessionReportPrinter ()); Expression tclone; try { // Note: clone context cannot be shared otherwise block mapping would leak tclone = source.Clone (new CloneContext ()); tclone = tclone.Resolve (ec, ResolveFlags.Type); if (ec.Report.Errors > 0) tclone = null; } finally { ec.Report.SetPrinter (old_printer); } if (tclone is TypeExpr) { Arguments args = new Arguments (1); args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location))); return new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec); } } // This means its really a statement. if (clone.Type.Kind == MemberKind.Void || clone is DynamicInvocation || clone is Assign) { return clone; } source = clone; return base.DoResolve (ec); }
protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) { Arguments binder_args = new Arguments (4); binder_args.Add (new Argument (new BinderFlags (flags, this))); binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args); }
public override Expression CreateExpressionTree (ResolveContext ec) { if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) { // Optimized version, also avoids referencing literal internal type Arguments args = new Arguments (1); args.Add (new Argument (this)); return CreateExpressionFactoryCall (ec, "Constant", args); } return base.CreateExpressionTree (ec); }
protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) { var setter_args = new Arguments (Arguments.Count + 1); setter_args.AddRange (Arguments); setter_args.Add (new Argument (rhs)); return setter_args; }
protected override Expression DoResolve (ResolveContext ec) { CloneContext cc = new CloneContext (); Expression clone = source.Clone (cc); // // A useful feature for the REPL: if we can resolve the expression // as a type, Describe the type; // if (Evaluator.DescribeTypeExpressions){ var old_printer = Evaluator.SetPrinter (new StreamReportPrinter (TextWriter.Null)); clone = clone.Resolve (ec); if (clone == null){ clone = source.Clone (cc); clone = clone.Resolve (ec, ResolveFlags.Type); if (clone == null){ Evaluator.SetPrinter (old_printer); clone = source.Clone (cc); clone = clone.Resolve (ec); return null; } Arguments args = new Arguments (1); args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location))); source = new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec); } Evaluator.SetPrinter (old_printer); } else { clone = clone.Resolve (ec); if (clone == null) return null; } // This means its really a statement. if (clone.Type == TypeManager.void_type){ source = source.Resolve (ec); target = null; type = TypeManager.void_type; eclass = ExprClass.Value; return this; } return base.DoResolve (ec); }
protected override Expression ResolveConversions (ResolveContext ec) { TypeSpec target_type = target.Type; // // 1. the return type is implicitly convertible to the type of target // if (Convert.ImplicitConversionExists (ec, source, target_type)) { source = Convert.ImplicitConversion (ec, source, target_type, loc); return this; } // // Otherwise, if the selected operator is a predefined operator // Binary b = source as Binary; if (b != null) { // // 2a. the operator is a shift operator // // 2b. the return type is explicitly convertible to the type of x, and // y is implicitly convertible to the type of x // if ((b.Oper & Binary.Operator.ShiftMask) != 0 || Convert.ImplicitConversionExists (ec, right, target_type)) { source = Convert.ExplicitConversion (ec, source, target_type, loc); return this; } } if (source.Type == InternalType.Dynamic) { Arguments arg = new Arguments (1); arg.Add (new Argument (source)); return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec); } right.Error_ValueCannotBeConverted (ec, loc, target_type, false); return null; }
public override Expression CreateExpressionTree (ResolveContext ec) { var args = new Arguments (1); args.Add (new Argument (expr.CreateExpressionTree (ec))); return CreateExpressionFactoryCall (ec, "Quote", args); }
public override Expression DoResolve(ResolveContext ec) { right = right.Resolve(ec); if (right == null) { return(null); } MemberAccess ma = target as MemberAccess; using (ec.Set(ResolveContext.Options.CompoundAssignmentScope)) { target = target.Resolve(ec); } if (target == null) { return(null); } if (target is MethodGroupExpr) { ec.Report.Error(1656, loc, "Cannot assign to `{0}' because it is a `{1}'", ((MethodGroupExpr)target).Name, target.ExprClassName); return(null); } if (target is EventExpr) { return(new EventAddOrRemove(target, op, right, loc).DoResolve(ec)); } // // Only now we can decouple the original source/target // into a tree, to guarantee that we do not have side // effects. // if (left == null) { left = new TargetExpression(target); } source = new Binary(op, left, right, true); // TODO: TargetExpression breaks MemberAccess composition if (target is DynamicMemberBinder) { Arguments targs = ((DynamicMemberBinder)target).Arguments; source = source.Resolve(ec); Arguments args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(source)); source = new DynamicMemberBinder(true, ma.Name, args, loc).Resolve(ec); // Handles possible event addition/subtraction if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { args = new Arguments(2); args.AddRange(targs); args.Add(new Argument(right)); string method_prefix = op == Binary.Operator.Addition ? Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; Expression invoke = new DynamicInvocation( new MemberAccess(right, method_prefix + ma.Name, loc), args, loc).Resolve(ec); args = new Arguments(1); args.AddRange(targs); source = new DynamicEventCompoundAssign(ma.Name, args, (ExpressionStatement)source, (ExpressionStatement)invoke, loc).Resolve(ec); } return(source); } return(base.DoResolve(ec)); }