Ejemplo n.º 1
0
        private void AddInitialization(ReadOnlyCollectionBuilder <MSAst.Expression> block)
        {
            if (IsModule)
            {
                block.Add(AssignValue(GetVariableExpression(FileVariable), Ast.Constant(ModuleFileName)));
                block.Add(AssignValue(GetVariableExpression(NameVariable), Ast.Constant(ModuleName)));
                block.Add(AssignValue(GetVariableExpression(PackageVariable), Ast.Constant(null)));
                block.Add(AssignValue(GetVariableExpression(SpecVariable), Ast.Constant(null)));
            }

            if (_languageFeatures != ModuleOptions.None || IsModule)
            {
                block.Add(
                    Ast.Call(
                        AstMethods.ModuleStarted,
                        LocalContext,
                        AstUtils.Constant(_languageFeatures)
                        )
                    );
            }
        }
Ejemplo n.º 2
0
 public Expression CreateExpression()
 {
     if (_infos == null)
     {
         return(Expression.New(
                    typeof(CallSignature).GetConstructor(new Type[] { typeof(int) }),
                    AstUtils.Constant(ArgumentCount)
                    ));
     }
     else
     {
         Expression[] args = new Expression[_infos.Length];
         for (int i = 0; i < args.Length; i++)
         {
             args[i] = _infos[i].CreateExpression();
         }
         return(Expression.New(
                    typeof(CallSignature).GetConstructor(new Type[] { typeof(Argument[]) }),
                    Expression.NewArrayInit(typeof(Argument), args)
                    ));
     }
 }
Ejemplo n.º 3
0
        public DynamicMetaObject GetIsCallable(DynamicMetaObject target)
        {
            // IsCallable() is tightly tied to Call actions. So in general, we need the call-action providers to also
            // provide IsCallable() status.
            // This is just a rough fallback. We could also attempt to simulate the default CallBinder logic to see
            // if there are any applicable calls targets, but that would be complex (the callbinder wants the argument list,
            // which we don't have here), and still not correct.
            BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType);

            bool callable = false;

            if (typeof(Delegate).IsAssignableFrom(target.LimitType) ||
                typeof(MethodGroup).IsAssignableFrom(target.LimitType))
            {
                callable = true;
            }

            return(new DynamicMetaObject(
                       AstUtils.Constant(callable),
                       restrictions
                       ));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Builds the restrictions for calling with keyword arguments.  The restrictions include
        /// tests on the individual keys of the dictionary to ensure they have the same names.
        /// </summary>
        private static BindingRestrictions MakeParamsDictionaryTest(IList <DynamicMetaObject> args, bool testTypes)
        {
            IDictionary           dict     = (IDictionary)args[args.Count - 1].Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            // verify the dictionary has the same count and arguments.

            string[] names = new string[dict.Count];
            Type[]   types = testTypes ? new Type[dict.Count] : null;
            int      index = 0;

            while (dictEnum.MoveNext())
            {
                string name = dictEnum.Entry.Key as string;
                if (name == null)
                {
                    throw ScriptingRuntimeHelpers.SimpleTypeError(
                              $"expected string for dictionary argument got {dictEnum.Entry.Key}");
                }
                names[index] = name;
                if (types != null)
                {
                    types[index] = CompilerHelpers.GetType(dictEnum.Entry.Value);
                }
                index++;
            }

            return(BindingRestrictions.GetExpressionRestriction(
                       Ast.AndAlso(
                           Ast.TypeIs(args[args.Count - 1].Expression, typeof(IDictionary)),
                           Ast.Call(
                               typeof(BinderOps).GetMethod("CheckDictionaryMembers"),
                               Ast.Convert(args[args.Count - 1].Expression, typeof(IDictionary)),
                               AstUtils.Constant(names),
                               testTypes ? AstUtils.Constant(types) : AstUtils.Constant(null, typeof(Type[]))
                               )
                           )
                       ));
        }
Ejemplo n.º 5
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression methodDefinitionVariable = gen.CurrentScope.DefineHiddenVariable(
                "#method_" + _name, typeof(RubyMethodInfo)
                );

            return(Methods.MethodDefined.OpCall(
                       Ast.Assign(methodDefinitionVariable,
                                  Methods.DefineMethod.OpCall(
                                      (_target != null) ? _target.TransformRead(gen) : gen.CurrentSelfVariable, // target
                                      Ast.Constant((gen.SavingToDisk) ? (object)new Serializable(this) : this),
                                      gen.CurrentScopeVariable,
                                      Ast.Constant(_target != null),                  // isSingleton?
                                      AstUtils.Constant(_name),
                                      TransformBody(gen, methodDefinitionVariable),
                                      Ast.Constant(_parameters.MandatoryCount),
                                      Ast.Constant(_parameters.OptionalCount),
                                      Ast.Constant(_parameters.Array != null)         // hasUnsplatParameter
                                      )
                                  )
                       ));
        }
Ejemplo n.º 6
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorSetMemberBody(SetOrDeleteMemberInfo memInfo, DynamicMetaObject self, DynamicMetaObject target, Type type, string name)
        {
            if (self != null)
            {
                MethodInfo setMem = GetMethod(type, name);
                if (setMem != null)
                {
                    ParameterExpression tmp = Ast.Variable(target.Expression.Type, "setValue");
                    memInfo.Body.AddVariable(tmp);

                    var callMo = MakeCallExpression(
                        memInfo.ResolutionFactory,
                        setMem,
                        self.Clone(AstUtils.Convert(self.Expression, type)),
                        new DynamicMetaObject(AstUtils.Constant(memInfo.Name), BindingRestrictions.Empty, memInfo.Name),
                        target.Clone(tmp)
                        );

                    var call = Ast.Block(Ast.Assign(tmp, target.Expression), callMo.Expression);

                    if (setMem.ReturnType == typeof(bool))
                    {
                        memInfo.Body.AddCondition(
                            call,
                            tmp
                            );
                    }
                    else
                    {
                        memInfo.Body.FinishCondition(Ast.Block(call, AstUtils.Convert(tmp, typeof(object))));
                    }

                    return(setMem.ReturnType != typeof(bool));
                }
            }

            return(false);
        }
Ejemplo n.º 7
0
        private Expression VisitYield(YieldExpression node)
        {
            if (node.Target != _generator.Target)
            {
                throw new InvalidOperationException("yield and generator must have the same LabelTarget object");
            }

            var value = Visit(node.Value);

            var block = new ReadOnlyCollectionBuilder <Expression>();

            if (value == null)
            {
                // Yield break
                block.Add(Expression.Assign(_state, AstUtils.Constant(Finished)));
                if (_inTryWithFinally)
                {
                    block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
                }
                block.Add(Expression.Goto(_returnLabels.Peek()));
                return(Expression.Block(block));
            }

            // Yield return
            block.Add(MakeAssign(_current, value));
            YieldMarker marker = GetYieldMarker(node);

            block.Add(Expression.Assign(_state, AstUtils.Constant(marker.State)));
            if (_inTryWithFinally)
            {
                block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
            }
            block.Add(Expression.Goto(_returnLabels.Peek()));
            block.Add(Expression.Label(marker.Label));
            block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterNone)));
            block.Add(Utils.Empty());
            return(Expression.Block(block));
        }
Ejemplo n.º 8
0
        public override DynamicMetaObject GetValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type)
        {
            if (Field.IsLiteral)
            {
                return(new DynamicMetaObject(
                           AstUtils.Constant(Field.GetValue(null), typeof(object)),
                           BindingRestrictions.Empty
                           ));
            }

            if (!IsStatic)
            {
                // return the field tracker...
                return(binder.ReturnMemberTracker(type, this));
            }

            if (Field.DeclaringType.ContainsGenericParameters)
            {
                return(null);
            }

            if (IsPublic && DeclaringType.IsPublic)
            {
                return(new DynamicMetaObject(
                           Expression.Convert(Expression.Field(null, Field), typeof(object)),
                           BindingRestrictions.Empty
                           ));
            }

            return(new DynamicMetaObject(
                       Expression.Call(
                           AstUtils.Convert(AstUtils.Constant(Field), typeof(FieldInfo)),
                           typeof(FieldInfo).GetMethod("GetValue"),
                           AstUtils.Constant(null)
                           ),
                       BindingRestrictions.Empty
                       ));
        }
Ejemplo n.º 9
0
        public DynamicMetaObject /*!*/ AddWarning(Expression /*!*/ codeContext, DynamicMetaObject /*!*/ result)
        {
            Expression warn = Expression.Call(
                typeof(PythonOps).GetMethod("Warn"),
                codeContext,
                AstUtils.Constant(_type),
                AstUtils.Constant(_message),
                AstUtils.Constant(ArrayUtils.EmptyObjects)
                );

            if (_condition != null)
            {
                warn = Expression.Condition(_condition, warn, AstUtils.Empty());
            }

            return(new DynamicMetaObject(
                       Expression.Block(
                           warn,
                           result.Expression
                           ),
                       result.Restrictions
                       ));
        }
Ejemplo n.º 10
0
        private static Expression MakeAmbiguousMatchError(MemberGroup members)
        {
            StringBuilder sb = new StringBuilder();

            foreach (MemberTracker mi in members)
            {
                if (sb.Length != 0)
                {
                    sb.Append(", ");
                }
                sb.Append(mi.MemberType);
                sb.Append(" : ");
                sb.Append(mi);
            }

            return(Ast.Throw(
                       Ast.New(
                           typeof(AmbiguousMatchException).GetConstructor(new Type[] { typeof(string) }),
                           AstUtils.Constant(sb.ToString())
                           ),
                       typeof(object)
                       ));
        }
Ejemplo n.º 11
0
        private Expression RewriteCallSite(CallSite site)
        {
            IExpressionSerializable serializer = site.Binder as IExpressionSerializable;

            if (serializer == null)
            {
                throw Error.GenNonSerializableBinder();
            }

            EnsureConstantPool();

            Type siteType = site.GetType();

            _constants.Add(Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression()));

            // rewrite the node...
            return(Visit(
                       AstUtils.Convert(
                           Expression.ArrayAccess(_constantPool, AstUtils.Constant(_constants.Count - 1)),
                           siteType
                           )
                       ));
        }
Ejemplo n.º 12
0
 // Determine if we can break directly to the label, or if we need to dispatch again
 // If we're breaking directly, we reset the _flowVariable, otherwise we just jump to
 // the next FlowLabel
 private Expression MakeFlowJump(LabelTarget target)
 {
     foreach (var block in _blocks)
     {
         if (block.LabelDefs.Contains(target))
         {
             break;
         }
         if (block.InFinally || block.HasFlow)
         {
             EnsureFlow(block);
             block.NeedFlowLabels.Add(target);
             // If we need to go through another finally, just jump
             // to its flow label
             return(Expression.Goto(block.FlowLabel));
         }
     }
     // Got here without needing flow, reset the flag and emit the real goto
     return(Expression.Block(
                Expression.Assign(_flowVariable, AstUtils.Constant(0)),
                Expression.Goto(target, _labels[target].Variable)
                ));
 }
Ejemplo n.º 13
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorDeleteMemberBody(SetOrDeleteMemberInfo delInfo, DynamicMetaObject instance, Type type, string name)
        {
            MethodInfo delMem = GetMethod(type, name);

            if (delMem != null)
            {
                DynamicMetaObject call = MakeCallExpression(delInfo.ResolutionFactory, delMem, instance, new DynamicMetaObject(AstUtils.Constant(delInfo.Name), BindingRestrictions.Empty, delInfo.Name));

                if (delMem.ReturnType == typeof(bool))
                {
                    delInfo.Body.AddCondition(
                        call.Expression,
                        AstUtils.Constant(null)
                        );
                }
                else
                {
                    delInfo.Body.FinishCondition(call);
                }

                return(delMem.ReturnType != typeof(bool));
            }
            return(false);
        }
Ejemplo n.º 14
0
        //TODO enable sharing of these custom delegates
        private Delegate CreateCustomDelegate(Type delegateType)
        {
            PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Synchronously compiling a custom delegate");

            var method             = delegateType.GetMethod("Invoke");
            var paramInfos         = method.GetParameters();
            var parameters         = new ParameterExpression[paramInfos.Length];
            var parametersAsObject = new Expression[paramInfos.Length];

            for (int i = 0; i < paramInfos.Length; i++)
            {
                ParameterExpression parameter = Expression.Parameter(paramInfos[i].ParameterType, paramInfos[i].Name);
                parameters[i]         = parameter;
                parametersAsObject[i] = Expression.Convert(parameter, typeof(object));
            }

            var data      = Expression.NewArrayInit(typeof(object), parametersAsObject);
            var self      = AstUtils.Constant(this);
            var runMethod = typeof(LightLambda).GetMethod("Run");
            var body      = Expression.Convert(Expression.Call(self, runMethod, data), method.ReturnType);
            var lambda    = Expression.Lambda(delegateType, body, parameters);

            return(lambda.Compile());
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Builds the restrictions for calling with a splatted argument array.  Ensures that the
        /// argument is still an ICollection of object and that it has the same number of arguments.
        /// </summary>
        private static BindingRestrictions MakeParamsTest(DynamicMetaObject splattee, bool testTypes)
        {
            IList <object> list = splattee.Value as IList <object>;

            if (list == null)
            {
                if (splattee.Value == null)
                {
                    return(BindingRestrictions.GetExpressionRestriction(Ast.Equal(splattee.Expression, AstUtils.Constant(null))));
                }

                return(BindingRestrictions.GetTypeRestriction(splattee.Expression, splattee.Value.GetType()));
            }

            BindingRestrictions res = BindingRestrictions.GetExpressionRestriction(
                Ast.AndAlso(
                    Ast.TypeIs(splattee.Expression, typeof(IList <object>)),
                    Ast.Equal(
                        Ast.Property(
                            Ast.Convert(splattee.Expression, typeof(IList <object>)),
                            typeof(ICollection <object>).GetDeclaredProperty("Count")
                            ),
                        AstUtils.Constant(list.Count)
                        )
                    )
                );

            if (testTypes)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    res = res.Merge(
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(
                            Ast.Call(
                                AstUtils.Convert(
                                    splattee.Expression,
                                    typeof(IList <object>)
                                    ),
                                typeof(IList <object>).GetMethod("get_Item"),
                                AstUtils.Constant(i)
                                ),
                            CompilerHelpers.GetType(list[i])
                            )
                        );
                }
            }

            return(res);
        }
Ejemplo n.º 16
0
        internal Expression Reduce()
        {
            // Visit body
            Expression body = Visit(_generator.Body);

            Debug.Assert(_returnLabels.Count == 1);

            // Add the switch statement to the body
            int count = _yields.Count;
            var cases = new SwitchCase[count + 1];

            for (int i = 0; i < count; i++)
            {
                cases[i] = Expression.SwitchCase(Expression.Goto(_yields[i].Label), AstUtils.Constant(_yields[i].State));
            }
            cases[count] = Expression.SwitchCase(Expression.Goto(_returnLabels.Peek()), AstUtils.Constant(Finished));

            Type generatorNextOfT = typeof(GeneratorNext <>).MakeGenericType(_generator.Target.Type);

            // Create the lambda for the GeneratorNext<T>, hoisting variables
            // into a scope outside the lambda
            var allVars = new List <ParameterExpression>(_vars);

            allVars.AddRange(_temps);

            // Collect temps that don't have to be closed over
            var innerTemps = new ReadOnlyCollectionBuilder <ParameterExpression>(1 + (_labelTemps?.Count ?? 0));

            innerTemps.Add(_gotoRouter);
            if (_labelTemps != null)
            {
                foreach (LabelInfo info in _labelTemps.Values)
                {
                    innerTemps.Add(info.Temp);
                }
            }

            body = Expression.Block(
                allVars,
                Expression.Lambda(
                    generatorNextOfT,
                    Expression.Block(
                        innerTemps,
                        Expression.Switch(Expression.Assign(_gotoRouter, _state), cases),
                        body,
                        Expression.Assign(_state, AstUtils.Constant(Finished)),
                        Expression.Label(_returnLabels.Peek())
                        ),
                    _generator.Name,
                    new ParameterExpression[] { _state, _current }
                    )
                );

            // Enumerable factory takes Func<GeneratorNext<T>> instead of GeneratorNext<T>
            if (_generator.IsEnumerable)
            {
                body = Expression.Lambda(body);
            }

            // We can't create a ConstantExpression of _debugCookies array here because we walk the tree
            // after constants have already been rewritten.  Instead we create a NewArrayExpression node
            // which initializes the array with contents from _debugCookies
            Expression debugCookiesArray = null;

            if (_debugCookies != null)
            {
                Expression[] debugCookies = new Expression[_debugCookies.Count];
                for (int i = 0; i < _debugCookies.Count; i++)
                {
                    debugCookies[i] = AstUtils.Constant(_debugCookies[i]);
                }

                debugCookiesArray = Expression.NewArrayInit(
                    typeof(int),
                    debugCookies);
            }

            // Generate a call to ScriptingRuntimeHelpers.MakeGenerator<T>(args)
            return(Expression.Call(
                       typeof(ScriptingRuntimeHelpers),
                       "MakeGenerator",
                       new[] { _generator.Target.Type },
                       (debugCookiesArray != null)
                    ? new[] { body, debugCookiesArray }
                    : new[] { body }
                       ));
        }
Ejemplo n.º 17
0
        private SwitchExpression MakeYieldRouter(Type type, int start, int end, LabelTarget newTarget)
        {
            Debug.Assert(end > start);
            var cases = new SwitchCase[end - start];

            for (int i = start; i < end; i++)
            {
                YieldMarker y = _yields[i];
                cases[i - start] = Expression.SwitchCase(Expression.Goto(y.Label, type), AstUtils.Constant(y.State));
                // Any jumps from outer switch statements should go to the this
                // router, not the original label (which they cannot legally jump to)
                y.Label = newTarget;
            }
            return(Expression.Switch(_gotoRouter, Expression.Default(type), cases));
        }
Ejemplo n.º 18
0
        protected override Expression VisitTry(TryExpression node)
        {
            int startYields = _yields.Count;

            bool savedInTryWithFinally = _inTryWithFinally;

            if (node.Finally != null || node.Fault != null)
            {
                _inTryWithFinally = true;
            }
            Expression @try      = Visit(node.Body);
            int        tryYields = _yields.Count;

            IList <CatchBlock> handlers = Visit(node.Handlers, VisitCatchBlock);
            int catchYields             = _yields.Count;

            // push a new return label in case the finally block yields
            _returnLabels.Push(Expression.Label());
            // only one of these can be non-null
            Expression  @finally      = Visit(node.Finally);
            Expression  fault         = Visit(node.Fault);
            LabelTarget finallyReturn = _returnLabels.Pop();
            int         finallyYields = _yields.Count;

            _inTryWithFinally = savedInTryWithFinally;

            if (@try == node.Body &&
                handlers == node.Handlers &&
                @finally == node.Finally &&
                fault == node.Fault)
            {
                return(node);
            }

            // No yields, just return
            if (startYields == _yields.Count)
            {
                return(Expression.MakeTry(null, @try, @finally, fault, handlers));
            }

            if (fault != null && finallyYields != catchYields)
            {
                // No one needs this yet, and it's not clear how we should get back to
                // the fault
                throw new NotSupportedException("yield in fault block is not supported");
            }

            // If try has yields, we need to build a new try body that
            // dispatches to the yield labels
            var tryStart = Expression.Label();

            if (tryYields != startYields)
            {
                @try = Expression.Block(MakeYieldRouter(node.Body.Type, startYields, tryYields, tryStart), @try);
            }

            // Transform catches with yield to deferred handlers
            if (catchYields != tryYields)
            {
                var block = new List <Expression>();

                block.Add(MakeYieldRouter(node.Body.Type, tryYields, catchYields, tryStart));
                block.Add(null); // empty slot to fill in later

                for (int i = 0, n = handlers.Count; i < n; i++)
                {
                    CatchBlock c = handlers[i];

                    if (c == node.Handlers[i])
                    {
                        continue;
                    }

                    if (handlers.IsReadOnly)
                    {
                        handlers = handlers.ToArray();
                    }

                    // the variable that will be scoped to the catch block
                    var exceptionVar = Expression.Variable(c.Test, null);

                    // the variable that the catch block body will use to
                    // access the exception. We reuse the original variable if
                    // the catch block had one. It needs to be hoisted because
                    // the catch might contain yields.
                    var deferredVar = c.Variable ?? Expression.Variable(c.Test, null);
                    _vars.Add(deferredVar);

                    // We need to ensure that filters can access the exception
                    // variable
                    Expression filter = c.Filter;
                    if (filter != null && c.Variable != null)
                    {
                        filter = Expression.Block(new[] { c.Variable }, Expression.Assign(c.Variable, exceptionVar), filter);
                    }

                    // catch (ExceptionType exceptionVar) {
                    //     deferredVar = exceptionVar;
                    // }
                    handlers[i] = Expression.Catch(
                        exceptionVar,
                        Expression.Block(
                            Expression.Assign(deferredVar, exceptionVar),
                            Expression.Default(node.Body.Type)
                            ),
                        filter
                        );

                    // We need to rewrite rethrows into "throw deferredVar"
                    var catchBody = new RethrowRewriter {
                        Exception = deferredVar
                    }.Visit(c.Body);

                    // if (deferredVar != null) {
                    //     ... catch body ...
                    // }
                    block.Add(
                        Expression.Condition(
                            Expression.NotEqual(deferredVar, AstUtils.Constant(null, deferredVar.Type)),
                            catchBody,
                            Expression.Default(node.Body.Type)
                            )
                        );
                }

                block[1] = Expression.MakeTry(null, @try, null, null, new ReadOnlyCollection <CatchBlock>(handlers));
                @try     = Expression.Block(block);
                handlers = new CatchBlock[0]; // so we don't reuse these
            }

            if (finallyYields != catchYields)
            {
                // We need to add a catch block to save the exception, so we
                // can rethrow in case there is a yield in the finally. Also,
                // add logic for returning. It looks like this:
                //
                // try { ... } catch (Exception all) { saved = all; }
                // finally {
                //  if (_finallyReturnVar) goto finallyReturn;
                //   ...
                //   if (saved != null) throw saved;
                //   finallyReturn:
                // }
                // if (_finallyReturnVar) goto _return;

                // We need to add a catch(Exception), so if we have catches,
                // wrap them in a try
                if (handlers.Count > 0)
                {
                    @try     = Expression.MakeTry(null, @try, null, null, handlers);
                    handlers = new CatchBlock[0];
                }

                // NOTE: the order of these routers is important
                // The first call changes the labels to all point at "tryEnd",
                // so the second router will jump to "tryEnd"
                var        tryEnd          = Expression.Label();
                Expression inFinallyRouter = MakeYieldRouter(node.Body.Type, catchYields, finallyYields, tryEnd);
                Expression inTryRouter     = MakeYieldRouter(node.Body.Type, catchYields, finallyYields, tryStart);

                var all   = Expression.Variable(typeof(Exception), "e");
                var saved = Expression.Variable(typeof(Exception), "$saved$" + _temps.Count);
                _temps.Add(saved);
                @try = Expression.Block(
                    Expression.TryCatchFinally(
                        Expression.Block(
                            inTryRouter,
                            @try,
                            Expression.Assign(saved, AstUtils.Constant(null, saved.Type)),
                            Expression.Label(tryEnd)
                            ),
                        Expression.Block(
                            MakeSkipFinallyBlock(finallyReturn),
                            inFinallyRouter,
                            @finally,
                            Expression.Condition(
                                Expression.NotEqual(saved, AstUtils.Constant(null, saved.Type)),
                                Expression.Throw(saved),
                                Utils.Empty()
                                ),
                            Expression.Label(finallyReturn)
                            ),
                        Expression.Catch(all, Utils.Void(Expression.Assign(saved, all)))
                        ),
                    Expression.Condition(
                        Expression.Equal(_gotoRouter, AstUtils.Constant(GotoRouterYielding)),
                        Expression.Goto(_returnLabels.Peek()),
                        Utils.Empty()
                        )
                    );

                @finally = null;
            }
            else if (@finally != null)
            {
                // try or catch had a yield, modify finally so we can skip over it
                @finally = Expression.Block(
                    MakeSkipFinallyBlock(finallyReturn),
                    @finally,
                    Expression.Label(finallyReturn)
                    );
            }

            // Make the outer try, if needed
            if (handlers.Count > 0 || @finally != null || fault != null)
            {
                @try = Expression.MakeTry(null, @try, @finally, fault, handlers);
            }

            return(Expression.Block(Expression.Label(tryStart), @try));
        }
Ejemplo n.º 19
0
        /// <summary>
        /// WithStatement is translated to the DLR AST equivalent to
        /// the following Python code snippet (from with statement spec):
        ///
        /// mgr = (EXPR)
        /// exit = mgr.__exit__  # Not calling it yet
        /// value = mgr.__enter__()
        /// exc = True
        /// try:
        ///     VAR = value  # Only if "as VAR" is present
        ///     BLOCK
        /// except:
        ///     # The exceptional case is handled here
        ///     exc = False
        ///     if not exit(*sys.exc_info()):
        ///         raise
        ///     # The exception is swallowed if exit() returns true
        /// finally:
        ///     # The normal and non-local-goto cases are handled here
        ///     if exc:
        ///         exit(None, None, None)
        ///
        /// </summary>
        public override MSAst.Expression Reduce()
        {
            // Five statements in the result...
            ReadOnlyCollectionBuilder <MSAst.Expression>          statements = new ReadOnlyCollectionBuilder <MSAst.Expression>(6);
            ReadOnlyCollectionBuilder <MSAst.ParameterExpression> variables  = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression>(6);

            MSAst.ParameterExpression lineUpdated = Ast.Variable(typeof(bool), "$lineUpdated_with");
            variables.Add(lineUpdated);

            //******************************************************************
            // 1. mgr = (EXPR)
            //******************************************************************
            MSAst.ParameterExpression manager = Ast.Variable(typeof(object), "with_manager");
            variables.Add(manager);
            statements.Add(
                GlobalParent.AddDebugInfo(
                    Ast.Assign(
                        manager,
                        _contextManager
                        ),
                    new SourceSpan(GlobalParent.IndexToLocation(StartIndex), GlobalParent.IndexToLocation(_headerIndex))
                    )
                );

            //******************************************************************
            // 2. exit = mgr.__exit__  # Not calling it yet
            //******************************************************************
            MSAst.ParameterExpression exit = Ast.Variable(typeof(object), "with_exit");
            variables.Add(exit);
            statements.Add(
                MakeAssignment(
                    exit,
                    GlobalParent.Get(
                        "__exit__",
                        manager
                        )
                    )
                );

            //******************************************************************
            // 3. value = mgr.__enter__()
            //******************************************************************
            MSAst.ParameterExpression value = Ast.Variable(typeof(object), "with_value");
            variables.Add(value);
            statements.Add(
                GlobalParent.AddDebugInfoAndVoid(
                    MakeAssignment(
                        value,
                        Parent.Invoke(
                            new CallSignature(0),
                            Parent.LocalContext,
                            GlobalParent.Get(
                                "__enter__",
                                manager
                                )
                            )
                        ),
                    new SourceSpan(GlobalParent.IndexToLocation(StartIndex), GlobalParent.IndexToLocation(_headerIndex))
                    )
                );

            //******************************************************************
            // 4. exc = True
            //******************************************************************
            MSAst.ParameterExpression exc = Ast.Variable(typeof(bool), "with_exc");
            variables.Add(exc);
            statements.Add(
                MakeAssignment(
                    exc,
                    AstUtils.Constant(true)
                    )
                );

            //******************************************************************
            //  5. The final try statement:
            //
            //  try:
            //      VAR = value  # Only if "as VAR" is present
            //      BLOCK
            //  except:
            //      # The exceptional case is handled here
            //      exc = False
            //      if not exit(*sys.exc_info()):
            //          raise
            //      # The exception is swallowed if exit() returns true
            //  finally:
            //      # The normal and non-local-goto cases are handled here
            //      if exc:
            //          exit(None, None, None)
            //******************************************************************

            var previousException = Ast.Variable(typeof(Exception), "$previousException");

            variables.Add(previousException);

            MSAst.ParameterExpression exception;
            statements.Add(
                // try:
                AstUtils.Try(
                    AstUtils.Try(// try statement body
                        PushLineUpdated(false, lineUpdated),
                        Ast.Assign(previousException, Ast.Call(AstMethods.SaveCurrentException)),
                        _var != null ?
                        (MSAst.Expression)Ast.Block(
                            // VAR = value
                            _var.TransformSet(SourceSpan.None, value, PythonOperationKind.None),
                            // BLOCK
                            _body,
                            AstUtils.Empty()
                            ) :
                        // BLOCK
                        (MSAst.Expression)_body // except:, // try statement location
                        ).Catch(exception = Ast.Variable(typeof(Exception), "exception"),
                                                // Python specific exception handling code
                                TryStatement.GetTracebackHeader(
                                    this,
                                    exception,
                                    GlobalParent.AddDebugInfoAndVoid(
                                        Ast.Block(
                                            Ast.Call(AstMethods.SetCurrentException, Parent.LocalContext, exception),
                                            // exc = False
                                            MakeAssignment(
                                                exc,
                                                AstUtils.Constant(false)
                                                ),
                                            //  if not exit(*sys.exc_info()):
                                            //      raise
                                            AstUtils.IfThen(
                                                GlobalParent.Convert(
                                                    typeof(bool),
                                                    ConversionResultKind.ExplicitCast,
                                                    GlobalParent.Operation(
                                                        typeof(bool),
                                                        PythonOperationKind.IsFalse,
                                                        MakeExitCall(exit, exception)
                                                        )
                                                    ),
                                                UpdateLineUpdated(true),
                                                Ast.Throw(
                                                    Ast.Call(
                                                        AstMethods.MakeRethrowExceptionWorker,
                                                        exception
                                                        )
                                                    )
                                                )
                                            ),
                                        _body.Span
                                        )
                                    ),
                                PopLineUpdated(lineUpdated),
                                Ast.Empty()
                                )
                    // finally:
                    ).Finally(
                    Ast.Call(AstMethods.RestoreCurrentException, previousException),
                    //  if exc:
                    //      exit(None, None, None)
                    AstUtils.IfThen(
                        exc,
                        GlobalParent.AddDebugInfoAndVoid(
                            Ast.Block(
                                MSAst.DynamicExpression.Dynamic(
                                    GlobalParent.PyContext.Invoke(
                                        new CallSignature(3)        // signature doesn't include function
                                        ),
                                    typeof(object),
                                    new MSAst.Expression[] {
                Parent.LocalContext,
                exit,
                AstUtils.Constant(null),
                AstUtils.Constant(null),
                AstUtils.Constant(null)
            }
                                    ),
                                Ast.Empty()
                                ),
                            _contextManager.Span
                            )
                        )
                    )
                );

            statements.Add(AstUtils.Empty());
            return(Ast.Block(variables.ToReadOnlyCollection(), statements.ToReadOnlyCollection()));
        }
Ejemplo n.º 20
0
 protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed)
 {
     return(AstUtils.Constant(Activator.CreateInstance(ParameterInfo.ParameterType)));
 }
Ejemplo n.º 21
0
        protected override Expression VisitTry(TryExpression node)
        {
            // Visit finally/fault block first
            BlockInfo block = new BlockInfo {
                InFinally = true
            };

            _blocks.Push(block);
            Expression @finally = Visit(node.Finally);
            Expression fault    = Visit(node.Fault);

            block.InFinally = false;

            LabelTarget finallyEnd = block.FlowLabel;

            if (finallyEnd != null)
            {
                // Make a new target, which will be emitted after the try
                block.FlowLabel = Expression.Label();
            }

            Expression         @try     = Visit(node.Body);
            IList <CatchBlock> handlers = Visit(node.Handlers, VisitCatchBlock);

            _blocks.Pop();

            if (@try == node.Body &&
                handlers == node.Handlers &&
                @finally == node.Finally &&
                fault == node.Fault)
            {
                return(node);
            }

            if (!block.HasFlow)
            {
                return(Expression.MakeTry(null, @try, @finally, fault, handlers));
            }

            if (node.Type != typeof(void))
            {
                // This is not hard to support in principle, but not needed by anyone yet.
                throw new NotSupportedException("FinallyFlowControlExpression does not support TryExpressions of non-void type.");
            }

            //  If there is a control flow in finally, emit outer:
            //  try {
            //      // try block body and all catch handling
            //  } catch (Exception all) {
            //      saved = all;
            //  } finally {
            //      finally_body
            //      if (saved != null) {
            //          throw saved;
            //      }
            //  }
            //
            //  If we have a fault handler we turn this into the better:
            //  try {
            //      // try block body and all catch handling
            //  } catch (Exception all) {
            //      fault_body
            //      throw all
            //  }

            if (handlers.Count > 0)
            {
                @try = Expression.MakeTry(null, @try, null, null, handlers);
            }

            var saved = Expression.Variable(typeof(Exception), "$exception");
            var all   = Expression.Variable(typeof(Exception), "e");

            if (@finally != null)
            {
                handlers = new[] {
                    Expression.Catch(
                        all,
                        Expression.Block(
                            Expression.Assign(saved, all),
                            Utils.Default(node.Type)
                            )
                        )
                };
                @finally = Expression.Block(
                    @finally,
                    Expression.Condition(
                        Expression.NotEqual(saved, AstUtils.Constant(null, saved.Type)),
                        Expression.Throw(saved),
                        Utils.Empty()
                        )
                    );

                if (finallyEnd != null)
                {
                    @finally = Expression.Label(finallyEnd, @finally);
                }
            }
            else
            {
                Debug.Assert(fault != null);

                fault = Expression.Block(fault, Expression.Throw(all));
                if (finallyEnd != null)
                {
                    fault = Expression.Label(finallyEnd, fault);
                }
                handlers = new[] { Expression.Catch(all, fault) };
                fault    = null;
            }

            // Emit flow control
            return(Expression.Block(
                       new[] { saved },
                       Expression.MakeTry(null, @try, @finally, fault, handlers),
                       Expression.Label(block.FlowLabel),
                       MakeFlowControlSwitch(block)
                       ));
        }
Ejemplo n.º 22
0
 internal DynamicMetaObject /*!*/ InvokeFallback(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args, CallSignature sig, DynamicMetaObject errorSuggestion)
 {
     return
         (PythonProtocol.Call(this, target, args) ??
          Context.Binder.Create(sig, target, args, AstUtils.Constant(_context.SharedContext)) ??
          Context.Binder.Call(sig, errorSuggestion, new PythonOverloadResolverFactory(Context.Binder, AstUtils.Constant(_context.SharedContext)), target, args));
 }
Ejemplo n.º 23
0
        private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup properties, DynamicMetaObject errorSuggestion)
        {
            PropertyTracker info = (PropertyTracker)properties[0];

            MethodInfo setter = info.GetSetMethod(true);

            // Allow access to protected getters TODO: this should go, it supports IronPython semantics.
            if (setter != null && !setter.IsPublic && !setter.IsProtected())
            {
                if (!PrivateBinding)
                {
                    setter = null;
                }
            }

            if (setter != null)
            {
                // TODO (tomat): this used to use setter.ReflectedType, is it still correct?
                setter = CompilerHelpers.TryGetCallableMethod(targetType, setter);

                if (!PrivateBinding && !CompilerHelpers.IsVisible(setter))
                {
                    setter = null;
                }
            }

            if (setter != null)
            {
                if (info.IsStatic != (instance == null))
                {
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(
                            MakeStaticPropertyInstanceAccessError(
                                info,
                                true,
                                instance,
                                target
                                ),
                            typeof(object)
                            )
                        );
                }
                else if (info.IsStatic && info.DeclaringType != targetType)
                {
                    memInfo.Body.FinishError(
                        errorSuggestion ?? MakeError(
                            MakeStaticAssignFromDerivedTypeError(targetType, instance, info, target, memInfo.ResolutionFactory),
                            typeof(object)
                            )
                        );
                }
                else if (setter.ContainsGenericParameters)
                {
                    memInfo.Body.FinishCondition(
                        MakeGenericPropertyExpression(memInfo)
                        );
                }
                else if (setter.IsPublic && !setter.DeclaringType.IsValueType())
                {
                    if (instance == null)
                    {
                        memInfo.Body.FinishCondition(
                            Ast.Block(
                                AstUtils.SimpleCallHelper(
                                    setter,
                                    ConvertExpression(
                                        target.Expression,
                                        setter.GetParameters()[0].ParameterType,
                                        ConversionResultKind.ExplicitCast,
                                        memInfo.ResolutionFactory
                                        )
                                    ),
                                Ast.Constant(null)
                                )
                            );
                    }
                    else
                    {
                        memInfo.Body.FinishCondition(
                            MakeReturnValue(
                                MakeCallExpression(memInfo.ResolutionFactory, setter, instance, target),
                                target
                                )
                            );
                    }
                }
                else
                {
                    // TODO: Should be able to do better w/ value types.
                    memInfo.Body.FinishCondition(
                        MakeReturnValue(
                            Ast.Call(
                                AstUtils.Constant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties
                                typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }),
                                instance == null ? AstUtils.Constant(null) : AstUtils.Convert(instance.Expression, typeof(object)),
                                AstUtils.Convert(
                                    ConvertExpression(
                                        target.Expression,
                                        setter.GetParameters()[0].ParameterType,
                                        ConversionResultKind.ExplicitCast,
                                        memInfo.ResolutionFactory
                                        ),
                                    typeof(object)
                                    ),
                                Ast.NewArrayInit(typeof(object))
                                ),
                            target
                            )
                        );
                }
            }
            else
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeMissingMemberErrorForAssignReadOnlyProperty(targetType, instance, memInfo.Name), typeof(object)
                        )
                    );
            }
        }
        protected override MSAst.Expression VisitDebugInfo(MSAst.DebugInfoExpression node)
        {
            if (!node.IsClear)
            {
                MSAst.Expression transformedExpression;

                // Verify that DebugInfoExpression has valid SymbolDocumentInfo
                if (node.Document == null)
                {
                    throw new InvalidOperationException(
                              string.Format(
                                  CultureInfo.CurrentCulture,
                                  ErrorStrings.DebugInfoWithoutSymbolDocumentInfo,
                                  _locationCookie));
                }

                DebugSourceFile sourceFile = _debugContext.GetDebugSourceFile(
                    String.IsNullOrEmpty(node.Document.FileName) ? "<compile>" : node.Document.FileName);

                // Update the location cookie
                int locationCookie = _locationCookie++;
                if (!_transformToGenerator)
                {
                    MSAst.Expression tracebackCall = null;
                    if (locationCookie == 0)
                    {
                        tracebackCall = Ast.Empty();
                    }
                    else
                    {
                        tracebackCall = Ast.Call(
                            typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.OnTraceEvent)),
                            _thread,
                            AstUtils.Constant(locationCookie),
                            Ast.Convert(Ast.Constant(null), typeof(Exception))
                            );
                    }

                    transformedExpression = Ast.Block(
                        Ast.Assign(
                            _debugMarker,
                            AstUtils.Constant(locationCookie)
                            ),
                        Ast.IfThen(
                            Ast.GreaterThan(
                                Ast.Property(_sourceFilesToVariablesMap[sourceFile], "Mode"),
                                Ast.Constant((int)DebugMode.ExceptionsOnly)
                                ),
                            Ast.IfThen(
                                Ast.OrElse(
                                    Ast.Equal(
                                        Ast.Property(_sourceFilesToVariablesMap[sourceFile], "Mode"),
                                        Ast.Constant((int)DebugMode.FullyEnabled)
                                        ),
                                    Ast.ArrayIndex(
                                        _traceLocations,
                                        AstUtils.Constant(locationCookie)
                                        )
                                    ),
                                Ast.Block(
                                    _pushFrame ?? Ast.Empty(),
                                    tracebackCall
                                    )
                                )
                            )
                        );
                }
                else
                {
                    Debug.Assert(_generatorLabelTarget != null);

                    transformedExpression = Ast.Block(
                        AstUtils.YieldReturn(
                            _generatorLabelTarget,
                            _debugYieldValue,
                            locationCookie
                            )
                        );

                    // Update the variable scope map
                    if (_currentLocals.Count > 0)
                    {
                        BlockExpression curentBlock = _currentLocals.Peek();
                        if (!_variableScopeMapCache.TryGetValue(curentBlock, out IList <VariableInfo> scopedVaribles))
                        {
                            scopedVaribles = new List <VariableInfo>();
                            BlockExpression[] blocks = _currentLocals.ToArray();
                            for (int i = blocks.Length - 1; i >= 0; i--)
                            {
                                foreach (var variable in blocks[i].Variables)
                                {
                                    scopedVaribles.Add(_localsToVarInfos[variable]);
                                }
                            }

                            _variableScopeMapCache.Add(curentBlock, scopedVaribles);
                        }

                        _variableScopeMap.Add(locationCookie, scopedVaribles);
                    }

                    DebugSourceSpan span = new DebugSourceSpan(
                        sourceFile,
                        node.StartLine,
                        node.StartColumn,
                        node.EndLine,
                        node.EndColumn);

                    // Update the location-span map
                    _markerLocationMap.Add(locationCookie, span);
                }

                return(transformedExpression);
            }

            return(Ast.Empty());
        }
        protected override Expression VisitTry(TryExpression node)
        {
            MSAst.Expression b = Visit(node.Body);
            ReadOnlyCollection <CatchBlock> h = Visit(node.Handlers, VisitCatchBlock);

            MSAst.Expression y = Visit(node.Finally);
            MSAst.Expression f;

            _insideConditionalBlock = true;
            try {
                f = Visit(node.Fault);
            } finally {
                _insideConditionalBlock = false;
            }

            node = Ast.MakeTry(node.Type, b, y, f, h);

            List <MSAst.CatchBlock> newHandlers = null;

            MSAst.Expression newFinally = null;

            // If the TryStatement has any Catch blocks we need to insert the exception
            // event as a first statement so that we can be notified of first-chance exceptions.
            if (node.Handlers != null && node.Handlers.Count > 0)
            {
                newHandlers = new List <CatchBlock>();

                foreach (var catchBlock in node.Handlers)
                {
                    ParameterExpression exceptionVar = catchBlock.Variable ?? Ast.Parameter(catchBlock.Test, null);

                    Expression debugMarker, thread;
                    if (_transformToGenerator)
                    {
                        debugMarker = Ast.Call(
                            typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.GetCurrentSequencePointForGeneratorFrame)),
                            _frame
                            );

                        thread = Ast.Call(typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.GetThread)), _frame);
                    }
                    else
                    {
                        debugMarker = _debugMarker;
                        thread      = _thread;
                    }

                    MSAst.Expression exceptionEvent = Ast.Block(
                        // Rethrow ForceToGeneratorLoopException
                        AstUtils.If(
                            Ast.TypeIs(
                                exceptionVar,
                                typeof(ForceToGeneratorLoopException)
                                ),
                            Ast.Throw(exceptionVar)
                            ),
                        AstUtils.If(
                            Ast.Equal(_globalDebugMode, AstUtils.Constant((int)DebugMode.FullyEnabled)),
                            _pushFrame ?? Ast.Empty(),
                            Ast.Call(
                                typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.OnTraceEvent)),
                                thread,
                                debugMarker,
                                exceptionVar
                                )
                            )
                        );

                    newHandlers.Add(Ast.MakeCatchBlock(
                                        catchBlock.Test,
                                        exceptionVar,
                                        Ast.Block(
                                            exceptionEvent,
                                            catchBlock.Body
                                            ),
                                        catchBlock.Filter
                                        ));
                }
            }

            if (!_transformToGenerator && node.Finally != null)
            {
                // Prevent the user finally block from running if the frame is currently remapping to generator
                newFinally = AstUtils.If(
                    Ast.Not(
                        Ast.Call(
                            typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.IsCurrentLeafFrameRemappingToGenerator)),
                            _thread
                            )
                        ),
                    node.Finally
                    );
            }

            if (newHandlers != null || newFinally != null)
            {
                node = Ast.MakeTry(
                    node.Type,
                    node.Body,
                    newFinally ?? node.Finally,
                    node.Fault,
                    newHandlers != null ? (IEnumerable <CatchBlock>)newHandlers : node.Handlers
                    );
            }

            return(node);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Returns an expression which creates the function object.
        /// </summary>
        internal MSAst.Expression MakeFunctionExpression()
        {
            var defaults    = new List <MSAst.Expression>();
            var kwdefaults  = new List <MSAst.Expression>();
            var annotations = new List <MSAst.Expression>();

            if (ReturnAnnotation != null)
            {
                // value needs to come before key in the array
                annotations.Add(AstUtils.Convert(ReturnAnnotation, typeof(object)));
                annotations.Add(Ast.Constant("return", typeof(string)));
            }

            foreach (var param in _parameters)
            {
                if (param.Kind == ParameterKind.Normal && param.DefaultValue != null)
                {
                    defaults.Add(AstUtils.Convert(param.DefaultValue, typeof(object)));
                }

                if (param.Kind == ParameterKind.KeywordOnly && param.DefaultValue != null)
                {
                    // value needs to come before key in the array
                    kwdefaults.Add(AstUtils.Convert(param.DefaultValue, typeof(object)));
                    kwdefaults.Add(Ast.Constant(param.Name, typeof(string)));
                }

                if (param.Annotation != null)
                {
                    // value needs to come before key in the array
                    annotations.Add(AstUtils.Convert(param.Annotation, typeof(object)));
                    annotations.Add(Ast.Constant(param.Name, typeof(string)));
                }
            }

            MSAst.Expression funcCode = GlobalParent.Constant(GetOrMakeFunctionCode());
            FuncCodeExpr = funcCode;

            MSAst.Expression ret;
            if (EmitDebugFunction())
            {
                LightLambdaExpression code = CreateFunctionLambda();

                // we need to compile all of the debuggable code together at once otherwise mdbg gets confused.  If we're
                // in tracing mode we'll still compile things one off though just to keep things simple.  The code will still
                // be debuggable but naive debuggers like mdbg will have more issues.
                ret = Ast.Call(
                    AstMethods.MakeFunctionDebug,                                                   // method
                    Parent.LocalContext,                                                            // 1. Emit CodeContext
                    FuncCodeExpr,                                                                   // 2. FunctionCode
                    ((IPythonGlobalExpression)GetVariableExpression(_nameVariable)).RawValue(),     // 3. module name
                    defaults.Count == 0 ?                                                           // 4. default values
                    AstUtils.Constant(null, typeof(object[])) :
                    (MSAst.Expression)Ast.NewArrayInit(typeof(object), defaults),
                    kwdefaults.Count == 0 ? AstUtils.Constant(null, typeof(PythonDictionary)) :
                    (MSAst.Expression)Ast.Call(                                                     // 5. kwdefaults
                        AstMethods.MakeDictFromItems,
                        Ast.NewArrayInit(
                            typeof(object),
                            kwdefaults
                            )
                        ),
                    annotations.Count == 0 ? AstUtils.Constant(null, typeof(PythonDictionary)) :
                    (MSAst.Expression)Ast.Call(                                                     // 6. annotations
                        AstMethods.MakeDictFromItems,
                        Ast.NewArrayInit(
                            typeof(object),
                            annotations
                            )
                        ),
                    IsGenerator ?
                    (MSAst.Expression) new PythonGeneratorExpression(code, GlobalParent.PyContext.Options.CompilationThreshold) :
                    (MSAst.Expression)code
                    );
            }
            else
            {
                ret = Ast.Call(
                    AstMethods.MakeFunction,                                                        // method
                    Parent.LocalContext,                                                            // 1. Emit CodeContext
                    FuncCodeExpr,                                                                   // 2. FunctionCode
                    ((IPythonGlobalExpression)GetVariableExpression(_nameVariable)).RawValue(),     // 3. module name
                    defaults.Count == 0 ?                                                           // 4. default values
                    AstUtils.Constant(null, typeof(object[])) :
                    (MSAst.Expression)Ast.NewArrayInit(typeof(object), defaults),
                    kwdefaults.Count == 0 ? AstUtils.Constant(null, typeof(PythonDictionary)) :
                    (MSAst.Expression)Ast.Call(                                                     // 5. kwdefaults
                        AstMethods.MakeDictFromItems,
                        Ast.NewArrayInit(
                            typeof(object),
                            kwdefaults
                            )
                        ),
                    annotations.Count == 0 ? AstUtils.Constant(null, typeof(PythonDictionary)) :
                    (MSAst.Expression)Ast.Call(                                                     // 6. annotations
                        AstMethods.MakeDictFromItems,
                        Ast.NewArrayInit(
                            typeof(object),
                            annotations
                            )
                        )
                    );
            }

            return(AddDecorators(ret, Decorators));
        }
Ejemplo n.º 27
0
 internal override MSA.Expression /*!*/ TransformWriteVariable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ rightValue)
 {
     if (gen.CompilerOptions.IsEval || gen.GetCurrentNonSingletonModule() != null)
     {
         return(Methods.SetClassVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name)));
     }
     else
     {
         return(Methods.SetObjectClassVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name)));
     }
 }
Ejemplo n.º 28
0
        private void CreateFunctionInstructions(LightCompiler compiler)
        {
            // emit context if we have a special local context
            CodeContext globalContext = null;

            compiler.Compile(Parent.LocalContext);

            // emit name if necessary
            PythonGlobal globalName = null;

            if (GetVariableExpression(_nameVariable) is PythonGlobalVariableExpression name)
            {
                globalName = name.Global;
            }
            else
            {
                compiler.Compile(((IPythonGlobalExpression)GetVariableExpression(_nameVariable)).RawValue());
            }

            // emit defaults
            int defaultCount = 0;

            for (int i = _parameters.Length - 1; i >= 0; i--)
            {
                var param = _parameters[i];
                if (param.Kind == ParameterKind.Normal && param.DefaultValue != null)
                {
                    compiler.Compile(AstUtils.Convert(param.DefaultValue, typeof(object)));
                    defaultCount++;
                }
            }

            // emit kwdefaults
            int kwdefaultCount = 0;

            for (int i = _parameters.Length - 1; i >= 0; i--)
            {
                var param = _parameters[i];
                if (param.Kind == ParameterKind.KeywordOnly && param.DefaultValue != null)
                {
                    compiler.Compile(AstUtils.Convert(param.DefaultValue, typeof(object)));
                    compiler.Compile(AstUtils.Constant(param.Name, typeof(string)));
                    kwdefaultCount++;
                }
            }

            // emit annotations
            int annotationCount = 0;

            if (ReturnAnnotation != null)
            {
                compiler.Compile(AstUtils.Convert(ReturnAnnotation, typeof(object)));
                compiler.Compile(AstUtils.Constant("return", typeof(string)));
                annotationCount++;
            }

            for (int i = _parameters.Length - 1; i >= 0; i--)
            {
                var param = _parameters[i];
                if (param.Annotation != null)
                {
                    compiler.Compile(AstUtils.Convert(param.Annotation, typeof(object)));
                    compiler.Compile(AstUtils.Constant(param.Name, typeof(string)));
                    annotationCount++;
                }
            }

            compiler.Instructions.Emit(new FunctionDefinitionInstruction(globalContext, this, defaultCount, kwdefaultCount, annotationCount, globalName));
        }
Ejemplo n.º 29
0
        private Microsoft.Scripting.Ast.LightExpression <Func <CodeContext, CodeContext> > MakeClassBody()
        {
            // we always need to create a nested context for class defs

            var init   = new List <MSAst.Expression>();
            var locals = new ReadOnlyCollectionBuilder <MSAst.ParameterExpression>();

            locals.Add(LocalCodeContextVariable);
            locals.Add(PythonAst._globalContext);

            init.Add(Ast.Assign(PythonAst._globalContext, new GetGlobalContextExpression(_parentContextParam)));

            GlobalParent.PrepareScope(locals, init);

            CreateVariables(locals, init);

            var createLocal = CreateLocalContext(_parentContextParam);

            init.Add(Ast.Assign(LocalCodeContextVariable, createLocal));

            List <MSAst.Expression> statements = new List <MSAst.Expression>();

            // Create the body
            MSAst.Expression bodyStmt = _body;

            // __module__ = __name__
            MSAst.Expression modStmt = AssignValue(GetVariableExpression(_modVariable), GetVariableExpression(_modNameVariable));

            string doc = GetDocumentation(_body);

            if (doc != null)
            {
                statements.Add(
                    AssignValue(
                        GetVariableExpression(_docVariable),
                        AstUtils.Constant(doc)
                        )
                    );
            }

            if (_body.CanThrow && GlobalParent.PyContext.PythonOptions.Frames)
            {
                bodyStmt = AddFrame(LocalContext, FuncCodeExpr, bodyStmt);
                locals.Add(FunctionStackVariable);
            }

            bodyStmt = WrapScopeStatements(
                Ast.Block(
                    Ast.Block(init),
                    statements.Count == 0 ?
                    EmptyBlock :
                    Ast.Block(new ReadOnlyCollection <MSAst.Expression>(statements)),
                    modStmt,
                    bodyStmt,
                    LocalContext
                    ),
                _body.CanThrow
                );

            var lambda = AstUtils.LightLambda <Func <CodeContext, CodeContext> >(
                typeof(CodeContext),
                Ast.Block(
                    locals,
                    bodyStmt
                    ),
                Name + "$" + Interlocked.Increment(ref _classId),
                new[] { _parentContextParam }
                );

            return(lambda);
        }
Ejemplo n.º 30
0
        private void MakeFieldRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup fields, DynamicMetaObject errorSuggestion)
        {
            FieldTracker field = (FieldTracker)fields[0];

            // TODO: Tmp variable for target
            if (instance != null && field.DeclaringType.IsGenericType() && field.DeclaringType.GetGenericTypeDefinition() == typeof(StrongBox <>))
            {
                // work around a CLR bug where we can't access generic fields from dynamic methods.
                Type[] generic = field.DeclaringType.GetGenericArguments();
                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Assign(
                            Ast.Field(
                                AstUtils.Convert(instance.Expression, field.DeclaringType),
                                field.DeclaringType.GetDeclaredField("Value")
                                ),
                            AstUtils.Convert(target.Expression, generic[0])
                            ),
                        target
                        )
                    );
            }
            else if (field.IsInitOnly || field.IsLiteral)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeReadOnlyMemberError(targetType, memInfo.Name),
                        typeof(object)
                        )
                    );
            }
            else if (field.IsStatic && targetType != field.DeclaringType)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeStaticAssignFromDerivedTypeError(targetType, instance, field, target, memInfo.ResolutionFactory),
                        typeof(object)
                        )
                    );
            }
            else if (field.DeclaringType.IsValueType() && !field.IsStatic)
            {
                memInfo.Body.FinishError(
                    errorSuggestion ?? MakeError(
                        MakeSetValueTypeFieldError(field, instance, target),
                        typeof(object)
                        )
                    );
            }
            else if (field.IsPublic && field.DeclaringType.IsVisible())
            {
                if (!field.IsStatic && instance == null)
                {
                    memInfo.Body.FinishError(
                        Ast.Throw(
                            Ast.New(
                                typeof(ArgumentException).GetConstructor(new[] { typeof(string) }),
                                AstUtils.Constant("assignment to instance field w/o instance")
                                ),
                            typeof(object)
                            )
                        );
                }
                else
                {
                    memInfo.Body.FinishCondition(
                        MakeReturnValue(
                            Ast.Assign(
                                Ast.Field(
                                    field.IsStatic ?
                                    null :
                                    AstUtils.Convert(instance.Expression, field.DeclaringType),
                                    field.Field
                                    ),
                                ConvertExpression(target.Expression, field.FieldType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory)
                                ),
                            target
                            )
                        );
                }
            }
            else
            {
                Debug.Assert(field.IsStatic || instance != null);

                memInfo.Body.FinishCondition(
                    MakeReturnValue(
                        Ast.Call(
                            AstUtils.Convert(AstUtils.Constant(field.Field), typeof(FieldInfo)),
                            typeof(FieldInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object) }),
                            field.IsStatic ?
                            AstUtils.Constant(null) :
                            (Expression)AstUtils.Convert(instance.Expression, typeof(object)),
                            AstUtils.Convert(target.Expression, typeof(object))
                            ),
                        target
                        )
                    );
            }
        }