예제 #1
0
 public SlotInitAdapter(PythonTypeSlot/*!*/ slot, ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _slot = slot;
 }
예제 #2
0
 public MixedInitAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
 }
예제 #3
0
        private NewAdapter/*!*/ GetNewAdapter(ArgumentValues/*!*/ ai, PythonTypeSlot/*!*/ newInst, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext) {
            PythonContext state = PythonContext.GetPythonContext(call);

            if (Value.IsMixedNewStyleOldStyle()) {
                return new MixedNewAdapter(ai, state, codeContext);
            } else if (newInst == InstanceOps.New) {
                return new DefaultNewAdapter(ai, Value, state, codeContext);
            } else if (newInst is ConstructorFunction) {
                return new ConstructorNewAdapter(ai, Value, state, codeContext);
            } else if (newInst is BuiltinFunction) {
                return new BuiltinNewAdapter(ai, Value, ((BuiltinFunction)newInst), state, codeContext);
            }

            return new NewAdapter(ai, state, codeContext);
        }
예제 #4
0
 public ConstructorNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _creating = creating;
 }
예제 #5
0
 public CallAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext) {
     _argInfo = ai;
     _state = state;
     _restrictions = BindingRestrictions.Empty;
     _context = codeContext;
 }
예제 #6
0
        private void GetAdapters(ArgumentValues/*!*/ ai, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, out NewAdapter/*!*/ newAdapter, out InitAdapter/*!*/ initAdapter) {
            PythonTypeSlot newInst, init;

            Value.TryResolveSlot(PythonContext.GetPythonContext(call).SharedContext, "__new__", out newInst);
            Value.TryResolveSlot(PythonContext.GetPythonContext(call).SharedContext, "__init__", out init);

            // these are never null because we always resolve to __new__ or __init__ somewhere.
            Assert.NotNull(newInst, init);

            newAdapter = GetNewAdapter(ai, newInst, call, codeContext);
            initAdapter = GetInitAdapter(ai, init, call, codeContext);
        }
예제 #7
0
        private DynamicMetaObject /*!*/ MakeGenericTypeDefinitionError(DynamicMetaObjectBinder /*!*/ call, ArgumentValues /*!*/ ai, ValidationInfo /*!*/ valInfo)
        {
            Debug.Assert(Value.IsSystemType);
            string message = "cannot create instances of " + Value.Name + " because it is a generic type definition";

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           call.Throw(
                               Ast.New(
                                   typeof(TypeErrorException).GetConstructor(new Type[] { typeof(string) }),
                                   AstUtils.Constant(message)
                                   ),
                               typeof(object)
                               ),
                           GetErrorRestrictions(ai)
                           ),
                       ai.Arguments,
                       valInfo
                       ));
        }
예제 #8
0
        public ParserResult Parse([NotNull] string line)
        {
            var tokens = Tokenizer.Tokenize(line).Select(token => token?.Trim()).Where(token => token != null).ToList();

            if (tokens.Count < 1)
            {
                return(new ParserError(
                           Settings.Localization.Errors.NoInput,
                           new ArgumentException(
                               @"No argument values were provided so unable to find a command.", nameof(tokens)
                               )
                           ).AsResult());
            }

            var commandName = tokens[0];
            var command     = Find(commandName ?? throw new InvalidOperationException());

            if (command == null)
            {
                return(MissingCommandError.Create(commandName, Settings.Localization.Errors.CommandNotFound).AsResult());
            }

            var positionalArguments = 0;
            var parsed = new Dictionary <ICommandArgument, ArgumentValues>();
            var errors = new List <ParserError>();

            for (var tokenIndex = 1; tokenIndex < tokens.Count; ++tokenIndex)
            {
                var token = tokens[tokenIndex];

                if (token == null)
                {
                    throw new InvalidOperationException(@"None of the cleaned arguments should be null at this point.");
                }

                var canBeShortName = token.StartsWith(Settings.PrefixShort);
                if (canBeShortName)
                {
                    var expectedLength = Settings.PrefixShort.Length + 1;
                    var actualLength   = token.Contains('=') ? token.IndexOf('=') : token.Length;
                    canBeShortName = expectedLength == actualLength;
                }

                var canBeLongName = token.StartsWith(Settings.PrefixLong);
                if (canBeLongName)
                {
                    var actualLength         = token.Length;
                    var maximumInvalidLength = Settings.PrefixLong.Length + (token.Contains('=') ? 2 : 1);
                    canBeLongName = actualLength > maximumInvalidLength;
                }

                var isPositional = false;
                if (!canBeShortName && !canBeLongName)
                {
                    if (positionalArguments < command.PositionalArguments.Count)
                    {
                        isPositional = true;
                    }
                    else
                    {
                        errors.Add(new ParserError(Settings.Localization.Errors.BadArgumentFormat.ToString(token)));

                        continue;
                    }
                }

                if (canBeShortName && canBeLongName)
                {
                    errors.Add(
                        new ParserError(
                            Settings.Localization.Errors.IllegalArgumentFormat.ToString(
                                token, Settings.PrefixShort, Settings.PrefixLong
                                )
                            )
                        );

                    continue;
                }

                var cleanArgParts = token.Split('=');
                var cleanArgName  = cleanArgParts[0] ?? "";
                var cleanArgValue = (cleanArgParts.Length == 2 ? cleanArgParts[1] : null) ?? "";

                if (isPositional)
                {
                    cleanArgValue = cleanArgName;
                }

                var argument = isPositional ? command.PositionalArguments[positionalArguments] :
                               canBeShortName?command.FindArgument(cleanArgName[Settings.PrefixShort.Length]) :
                                   command.FindArgument(cleanArgName.Substring(Settings.PrefixLong.Length));

                if (argument == null)
                {
                    if (isPositional)
                    {
                        errors.Add(
                            UnhandledArgumentError.Create(
                                command.Name, positionalArguments, cleanArgValue,
                                Settings.Localization.Errors.UnhandledPositionalArgument
                                )
                            );
                    }
                    else
                    {
                        errors.Add(
                            UnhandledArgumentError.Create(
                                command.Name, cleanArgName, Settings.Localization.Errors.UnhandledNamedArgument
                                )
                            );
                    }

                    continue;
                }

                var argumentDisplayName = isPositional ? argument.Name : cleanArgName;

                var typeName = argument.ValueType.Name;
                if (Settings.Localization.TypeNames.TryGetValue(typeName, out var localizedType))
                {
                    typeName = localizedType;
                }

                List <object> values;
                if (parsed.TryGetValue(argument, out var argumentValues))
                {
                    if (!argument.AllowsMultiple)
                    {
                        errors.Add(
                            new ParserError(
                                Settings.Localization.Errors.DuplicateNamedArgument.ToString(argumentDisplayName), false
                                )
                            );

                        continue;
                    }

                    values = argumentValues.Values.ToList();
                }
                else
                {
                    values = new List <object>();
                }

                if (argument.IsFlag)
                {
                    if (!string.IsNullOrEmpty(cleanArgValue))
                    {
                        errors.Add(
                            new ParserError(
                                Settings.Localization.Errors.FlagArgumentsIgnoreValue.ToString(argumentDisplayName),
                                false
                                )
                            );
                    }

                    values.Add(true);
                }
                else if (argument.IsCollection)
                {
                    if (argument.Delimeter == null)
                    {
                    }
                    else
                    {
                        var defaultValue     = argument.ValueTypeDefault;
                        var parsedPartValues = cleanArgValue.Split(new[] { argument.Delimeter }, StringSplitOptions.None)
                                               .Select(
                            valuePart =>
                        {
                            if (string.IsNullOrEmpty(valuePart))
                            {
                                return(defaultValue);
                            }

                            if (TryParseArgument(
                                    argument.ValueType, defaultValue, valuePart, out var parsedPart
                                    ))
                            {
                                if (!argument.IsValueAllowed(parsedPart))
                                {
                                    errors.Add(
                                        new ParserError(
                                            Settings.Localization.Errors.InvalidArgumentValue.ToString(
                                                valuePart, argumentDisplayName
                                                )
                                            )
                                        );
                                }

                                return(parsedPart);
                            }

                            if (argument.ValueType != typeof(object))
                            {
                                errors.Add(
                                    new ParserError(
                                        Settings.Localization.Errors.InvalidArgumentValueWithType.ToString(
                                            valuePart, argumentDisplayName, typeName
                                            ), false
                                        )
                                    );
                            }
                            else
                            {
                                errors.Add(
                                    new ParserError(
                                        Settings.Localization.Errors.InvalidArgumentValue.ToString(
                                            valuePart, argumentDisplayName
                                            ), false
                                        )
                                    );
                            }

                            return(defaultValue);
                        }
                            );

                        values.AddRange(parsedPartValues);
                    }
                }
                else
                {
                    if (!TryParseArgument(argument.ValueType, argument.DefaultValue, cleanArgValue, out var value))
                    {
                        if (argument.ValueType != typeof(object))
                        {
                            errors.Add(
                                new ParserError(
                                    Settings.Localization.Errors.InvalidArgumentValueWithType.ToString(
                                        cleanArgValue, argumentDisplayName, typeName
                                        ), true
                                    )
                                );
                        }
                        else
                        {
                            errors.Add(
                                new ParserError(
                                    Settings.Localization.Errors.InvalidArgumentValue.ToString(
                                        cleanArgValue, argumentDisplayName
                                        ), false
                                    )
                                );
                        }
                    }

                    if (!argument.IsValueAllowed(value))
                    {
                        errors.Add(
                            new ParserError(

                                // TODO: DisallowedArgumentValue message instead
                                Settings.Localization.Errors.InvalidArgumentValue.ToString(value, argumentDisplayName)
                                )
                            );
                    }

                    values.Add(value);
                }

                parsed[argument] = new ArgumentValues(argumentDisplayName, values);

                if (isPositional)
                {
                    ++positionalArguments;
                }
            }

            var parserContext = new ParserContext
            {
                Command = command,
                Tokens  = tokens.ToImmutableList(),
                Errors  = errors.ToImmutableList(),
                Parsed  = parsed.ToImmutableDictionary()
            };

            var omitted = new List <ICommandArgument>();
            var missing = new List <ICommandArgument>();

            foreach (var argument in command.Arguments)
            {
                if (!argument.IsRequired(parserContext) || parsed.ContainsKey(argument))
                {
                    if (!parsed.ContainsKey(argument))
                    {
                        parsed[argument] = ConstructDefaultArgument(argument, true);
                        omitted.Add(argument);
                    }

                    continue;
                }

                if (argument.IsPositional)
                {
                    errors.Add(
                        MissingArgumentError.Create(
                            Settings.Localization.Errors.MissingPositionalArgument, argument.Name, commandName
                            )
                        );
                }
                else
                {
                    errors.Add(MissingArgumentError.Create(Settings.PrefixLong, argument.Name, commandName));
                }

                missing.Add(argument);
            }

            return(new ParserResult(command, new ArgumentValuesMap(parsed), errors, missing, omitted));
        }
예제 #9
0
 public BuiltinInitAdapter(ArgumentValues /*!*/ ai, BuiltinFunction /*!*/ method, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
     _method = method;
 }
예제 #10
0
        private DynamicMetaObject /*!*/ MakeIncorrectArgumentsForCallError(DynamicMetaObjectBinder /*!*/ call, ArgumentValues /*!*/ ai, ValidationInfo /*!*/ valInfo)
        {
            string message;

            if (Value.IsSystemType)
            {
                if (Value.UnderlyingSystemType.GetConstructors().Length == 0)
                {
                    // this is a type we can't create ANY instances of, give the user a half-way decent error message
                    message = "cannot create instances of " + Value.Name;
                }
                else
                {
                    message = InstanceOps.ObjectNewNoParameters;
                }
            }
            else
            {
                message = InstanceOps.ObjectNewNoParameters;
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           call.Throw(
                               Ast.New(
                                   typeof(TypeErrorException).GetConstructor(new Type[] { typeof(string) }),
                                   AstUtils.Constant(message)
                                   )
                               ),
                           GetErrorRestrictions(ai)
                           ),
                       ai.Arguments,
                       valInfo
                       ));
        }
예제 #11
0
 public SlotInitAdapter(PythonTypeSlot /*!*/ slot, ArgumentValues /*!*/ ai, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
     _slot = slot;
 }
예제 #12
0
 protected InitAdapter(ArgumentValues /*!*/ ai, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
 }
예제 #13
0
 public BuiltinNewAdapter(ArgumentValues /*!*/ ai, PythonType /*!*/ creating, BuiltinFunction /*!*/ ctor, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
     _creating = creating;
     _ctor     = ctor;
 }
예제 #14
0
        private DynamicMetaObject/*!*/ MakeGenericTypeDefinitionError(DynamicMetaObjectBinder/*!*/ call, ArgumentValues/*!*/ ai, ValidationInfo/*!*/ valInfo) {
            Debug.Assert(Value.IsSystemType);
            string message = "cannot create instances of " + Value.Name + " because it is a generic type definition";

            return BindingHelpers.AddDynamicTestAndDefer(
                call,
                new DynamicMetaObject(
                    call.Throw(
                        Ast.New(
                            typeof(TypeErrorException).GetConstructor(new Type[] { typeof(string) }),
                            AstUtils.Constant(message)
                        ),
                        typeof(object)
                    ),
                    GetErrorRestrictions(ai)
                ),
                ai.Arguments,
                valInfo
            );
        }
예제 #15
0
        private DynamicMetaObject /*!*/ MakeAbstractInstantiationError(DynamicMetaObjectBinder /*!*/ call, ArgumentValues /*!*/ ai, ValidationInfo /*!*/ valInfo)
        {
            CodeContext context = PythonContext.GetPythonContext(call).SharedContext;
            string      message = Value.GetAbstractErrorMessage(context);

            Debug.Assert(message != null);

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           Ast.Throw(
                               Ast.New(
                                   typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
                                   AstUtils.Constant(message)
                                   ),
                               typeof(object)
                               ),
                           GetErrorRestrictions(ai)
                           ),
                       ai.Arguments,
                       valInfo
                       ));
        }
예제 #16
0
        private BindingRestrictions/*!*/ GetErrorRestrictions(ArgumentValues/*!*/ ai) {
            BindingRestrictions res = Restrict(this.GetRuntimeType()).Restrictions;
            res = res.Merge(GetInstanceRestriction(ai));

            foreach (DynamicMetaObject mo in ai.Arguments) {
                if (mo.HasValue) {
                    res = res.Merge(mo.Restrict(mo.GetRuntimeType()).Restrictions);
                }
            }

            return res;
        }
예제 #17
0
 private static BindingRestrictions GetInstanceRestriction(ArgumentValues ai)
 {
     return(BindingRestrictions.GetInstanceRestriction(ai.Self.Expression, ai.Self.Value));
 }
예제 #18
0
 public DefaultInitAdapter(ArgumentValues/*!*/ ai, BinderState/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
 }
예제 #19
0
        /// <summary>
        /// Creating a Python type involves calling __new__ and __init__.  We resolve them
        /// and generate calls to either the builtin funcions directly or embed sites which
        /// call the slots at runtime.
        /// </summary>
        private DynamicMetaObject /*!*/ MakePythonTypeCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            ValidationInfo valInfo = MakeVersionCheck();

            DynamicMetaObject self = new RestrictedMetaObject(
                AstUtils.Convert(Expression, LimitType),
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
                Value
                );
            CallSignature  sig = BindingHelpers.GetCallSignature(call);
            ArgumentValues ai  = new ArgumentValues(sig, self, args);
            NewAdapter     newAdapter;
            InitAdapter    initAdapter;

            if (TooManyArgsForDefaultNew(call, args))
            {
                return(MakeIncorrectArgumentsForCallError(call, ai, valInfo));
            }
            else if (Value.UnderlyingSystemType.IsGenericTypeDefinition)
            {
                return(MakeGenericTypeDefinitionError(call, ai, valInfo));
            }
            else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext))
            {
                return(MakeAbstractInstantiationError(call, ai, valInfo));
            }

            DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name);

            if (translated != null)
            {
                return(translated);
            }

            GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
            PythonContext state = PythonContext.GetPythonContext(call);

            // get the expression for calling __new__
            DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);

            if (createExpr.Expression.Type == typeof(void))
            {
                return(BindingHelpers.AddDynamicTestAndDefer(
                           call,
                           createExpr,
                           args,
                           valInfo
                           ));
            }

            Expression          res;
            BindingRestrictions additionalRestrictions = BindingRestrictions.Empty;

            if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call)))
            {
                // we need to dynamically check the return value to see if it's a subtype of
                // the type that we are calling.  If it is then we need to call __init__/__del__
                // for the actual returned type.
                res = DynamicExpression.Dynamic(
                    Value.GetLateBoundInitBinder(sig),
                    typeof(object),
                    ArrayUtils.Insert(
                        codeContext,
                        Expression.Convert(createExpr.Expression, typeof(object)),
                        DynamicUtils.GetExpressions(args)
                        )
                    );
                additionalRestrictions = createExpr.Restrictions;
            }
            else
            {
                // just call the __init__ method, built-in types currently have
                // no wacky return values which don't return the derived type.

                // then get the statement for calling __init__
                ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
                Expression          tmpRead       = allocatedInst;
                DynamicMetaObject   initCall      = initAdapter.MakeInitCall(
                    state.Binder,
                    new RestrictedMetaObject(
                        AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
                        createExpr.Restrictions
                        )
                    );

                List <Expression> body = new List <Expression>();
                Debug.Assert(!HasFinalizer(call));

                // add the call to init if we need to
                if (initCall.Expression != tmpRead)
                {
                    // init can fail but if __new__ returns a different type
                    // no exception is raised.
                    DynamicMetaObject initStmt = initCall;

                    if (body.Count == 0)
                    {
                        body.Add(
                            Ast.Assign(allocatedInst, createExpr.Expression)
                            );
                    }

                    if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type))
                    {
                        // return type of object, we need to check the return type before calling __init__.
                        body.Add(
                            AstUtils.IfThen(
                                Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
                                initStmt.Expression
                                )
                            );
                    }
                    else
                    {
                        // just call the __init__ method, no type check necessary (TODO: need null check?)
                        body.Add(initStmt.Expression);
                    }
                }

                // and build the target from everything we have
                if (body.Count == 0)
                {
                    res = createExpr.Expression;
                }
                else
                {
                    body.Add(allocatedInst);
                    res = Ast.Block(body);
                }
                res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);

                additionalRestrictions = initCall.Restrictions;
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           res,
                           self.Restrictions.Merge(additionalRestrictions)
                           ),
                       ArrayUtils.Insert(this, args),
                       valInfo
                       ));
        }
예제 #20
0
        /// <summary>
        /// Creating a Python type involves calling __new__ and __init__.  We resolve them
        /// and generate calls to either the builtin funcions directly or embed sites which
        /// call the slots at runtime.
        /// </summary>
        private DynamicMetaObject/*!*/ MakePythonTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
            ValidationInfo valInfo = MakeVersionCheck();

            DynamicMetaObject self = new RestrictedMetaObject(
                AstUtils.Convert(Expression, LimitType),
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
                Value
            );
            CallSignature sig = BindingHelpers.GetCallSignature(call);
            ArgumentValues ai = new ArgumentValues(sig, self, args);
            NewAdapter newAdapter;
            InitAdapter initAdapter;

            if (TooManyArgsForDefaultNew(call, args)) {
                return MakeIncorrectArgumentsForCallError(call, ai, valInfo);
            } else if (Value.UnderlyingSystemType.IsGenericTypeDefinition()) {
                return MakeGenericTypeDefinitionError(call, ai, valInfo);
            } else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext)) {
                return MakeAbstractInstantiationError(call, ai, valInfo);
            }

            DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name);
            if (translated != null) {
                return translated;
            }

            GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
            PythonContext state = PythonContext.GetPythonContext(call);
            
            // get the expression for calling __new__
            DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);
            if (createExpr.Expression.Type == typeof(void)) {
                return BindingHelpers.AddDynamicTestAndDefer(
                    call,
                    createExpr,
                    args,                        
                    valInfo
                );                    
            }

            Expression res;
            BindingRestrictions additionalRestrictions = BindingRestrictions.Empty;
            if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call))) {
                // we need to dynamically check the return value to see if it's a subtype of
                // the type that we are calling.  If it is then we need to call __init__/__del__
                // for the actual returned type.
                res = DynamicExpression.Dynamic(
                    Value.GetLateBoundInitBinder(sig),
                    typeof(object),
                    ArrayUtils.Insert(
                        codeContext,
                        Expression.Convert(createExpr.Expression, typeof(object)),
                        DynamicUtils.GetExpressions(args)
                    )
                );
                additionalRestrictions = createExpr.Restrictions;
            } else {
                // just call the __init__ method, built-in types currently have
                // no wacky return values which don't return the derived type.

                // then get the statement for calling __init__
                ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
                Expression tmpRead = allocatedInst;
                DynamicMetaObject initCall = initAdapter.MakeInitCall(
                    state.Binder,
                    new RestrictedMetaObject(
                        AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
                        createExpr.Restrictions
                    )
                );

                List<Expression> body = new List<Expression>();
                Debug.Assert(!HasFinalizer(call));

                // add the call to init if we need to
                if (initCall.Expression != tmpRead) {
                    // init can fail but if __new__ returns a different type
                    // no exception is raised.
                    DynamicMetaObject initStmt = initCall;

                    if (body.Count == 0) {
                        body.Add(
                            Ast.Assign(allocatedInst, createExpr.Expression)
                        );
                    }

                    if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type)) {
                        // return type of object, we need to check the return type before calling __init__.
                        body.Add(
                            AstUtils.IfThen(
                                Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
                                initStmt.Expression
                            )
                        );
                    } else {
                        // just call the __init__ method, no type check necessary (TODO: need null check?)
                        body.Add(initStmt.Expression);
                    }
                }

                // and build the target from everything we have
                if (body.Count == 0) {
                    res = createExpr.Expression;
                } else {
                    body.Add(allocatedInst);
                    res = Ast.Block(body);
                }
                res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);

                additionalRestrictions = initCall.Restrictions;
            }

            return BindingHelpers.AddDynamicTestAndDefer(
                call,
                new DynamicMetaObject(
                    res,
                    self.Restrictions.Merge(additionalRestrictions)
                ),
                ArrayUtils.Insert(this, args),
                valInfo
            );
        }
예제 #21
0
 public CallAdapter(ArgumentValues /*!*/ ai, PythonContext /*!*/ state, Expression /*!*/ codeContext)
 {
     _argInfo = ai;
     _state   = state;
     _context = codeContext;
 }
예제 #22
0
 private InitAdapter/*!*/ GetInitAdapter(ArgumentValues/*!*/ ai, PythonTypeSlot/*!*/ init, DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext) {
     PythonContext state = PythonContext.GetPythonContext(call);
     if (Value.IsMixedNewStyleOldStyle()) {
         return new MixedInitAdapter(ai, state, codeContext);
     } else if ((init == InstanceOps.Init && !HasFinalizer(call)) || (Value == TypeCache.PythonType && ai.Arguments.Length == 2)) {
         return new DefaultInitAdapter(ai, state, codeContext);
     } else if (init is BuiltinMethodDescriptor) {
         return new BuiltinInitAdapter(ai, ((BuiltinMethodDescriptor)init).Template, state, codeContext);
     } else if (init is BuiltinFunction) {
         return new BuiltinInitAdapter(ai, (BuiltinFunction)init, state, codeContext);
     } else {
         return new SlotInitAdapter(init, ai, state, codeContext);
     }
 }
예제 #23
0
 public NewAdapter(ArgumentValues /*!*/ ai, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
 }
예제 #24
0
 public CallAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext) {
     _argInfo = ai;
     _state = state;
     _context = codeContext;
 }
예제 #25
0
 public DefaultNewAdapter(ArgumentValues /*!*/ ai, PythonType /*!*/ creating, PythonContext /*!*/ state, Expression /*!*/ codeContext)
     : base(ai, state, codeContext)
 {
     _creating = creating;
 }
예제 #26
0
 public BuiltinNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, BuiltinFunction/*!*/ ctor, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _creating = creating;
     _ctor = ctor;
 }
예제 #27
0
        /// <summary>
        /// Creating a Python type involves calling __new__ and __init__.  We resolve them
        /// and generate calls to either the builtin funcions directly or embed sites which
        /// call the slots at runtime.
        /// </summary>
        private DynamicMetaObject/*!*/ MakePythonTypeCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/[]/*!*/ args) {
            ValidationInfo valInfo = MakeVersionCheck();

            DynamicMetaObject self = new RestrictedMetaObject(
                AstUtils.Convert(Expression, LimitType),
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
                Value
            );
            ArgumentValues ai = new ArgumentValues(BindingHelpers.GetCallSignature(call), self, args);
            NewAdapter newAdapter;
            InitAdapter initAdapter;

            if (TooManyArgsForDefaultNew(call, args)) {
                return MakeIncorrectArgumentsForCallError(call, ai, valInfo);
            }

            GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
            BinderState state = BinderState.GetBinderState(call);
            
            // get the expression for calling __new__
            DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);
            if (createExpr.Expression.Type == typeof(void)) {
                return BindingHelpers.AddDynamicTestAndDefer(
                    call,
                    createExpr,
                    args,                        
                    valInfo
                );                    
            }

            // then get the statement for calling __init__
            ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
            Expression tmpRead = allocatedInst;
            DynamicMetaObject initCall = initAdapter.MakeInitCall(
                state.Binder,
                new RestrictedMetaObject(
                    AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
                    createExpr.Restrictions
                )
            );

            List<Expression> body = new List<Expression>();
            // then get the call to __del__ if we need one
            if (HasFinalizer(call)) {
                body.Add(
                    Ast.Assign(allocatedInst, createExpr.Expression)
                );
                body.Add(
                    GetFinalizerInitialization(call, allocatedInst)
                );
            }

            // add the call to init if we need to
            if (initCall.Expression != tmpRead) {
                // init can fail but if __new__ returns a different type
                // no exception is raised.
                DynamicMetaObject initStmt = initCall;

                if (body.Count == 0) {
                    body.Add(
                        Ast.Assign(allocatedInst, createExpr.Expression)
                    );
                }

                if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type)) {
                    // return type of object, we need to check the return type before calling __init__.
                    body.Add(
                        AstUtils.IfThen(
                            Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
                            initStmt.Expression
                        )
                    );
                } else {
                    // just call the __init__ method, no type check necessary (TODO: need null check?)
                    body.Add(initStmt.Expression);
                }
            }

            Expression res;
            // and build the target from everything we have
            if (body.Count == 0) {
                res = createExpr.Expression;
            } else {
                body.Add(allocatedInst);
                res = Ast.Block(body);
            }
            res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);

            return BindingHelpers.AddDynamicTestAndDefer(
                call,
                new DynamicMetaObject(
                    res,
                    self.Restrictions.Merge(initCall.Restrictions)
                ),
                ArrayUtils.Insert(this, args),
                valInfo
            );
        }
예제 #28
0
 public BuiltinInitAdapter(ArgumentValues/*!*/ ai, BuiltinFunction/*!*/ method, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _method = method;
 }
예제 #29
0
 public DefaultNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, BinderState/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _creating = creating;
 }
예제 #30
0
        private DynamicMetaObject/*!*/ MakeIncorrectArgumentsForCallError(DynamicMetaObjectBinder/*!*/ call, ArgumentValues/*!*/ ai, ValidationInfo/*!*/ valInfo) {
            string message;

            if (Value.IsSystemType) {
                if (Value.UnderlyingSystemType.GetConstructors().Length == 0) {
                    // this is a type we can't create ANY instances of, give the user a half-way decent error message
                    message = "cannot create instances of " + Value.Name;
                } else {
                    message = InstanceOps.ObjectNewNoParameters;
                }
            } else {
                message = InstanceOps.ObjectNewNoParameters;
            }

            return BindingHelpers.AddDynamicTestAndDefer(
                call,
                new DynamicMetaObject(
                    call.Throw(
                        Ast.New(
                            typeof(TypeErrorException).GetConstructor(new Type[] { typeof(string) }),
                            AstUtils.Constant(message)
                        )
                    ),
                    GetErrorRestrictions(ai)
                ), 
                ai.Arguments,                
                valInfo
            );
        }
예제 #31
0
 public MixedNewAdapter(ArgumentValues/*!*/ ai, BinderState/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
 }
예제 #32
0
        private DynamicMetaObject/*!*/ MakeAbstractInstantiationError(DynamicMetaObjectBinder/*!*/ call, ArgumentValues/*!*/ ai, ValidationInfo/*!*/ valInfo) {
            CodeContext context = PythonContext.GetPythonContext(call).SharedContext;
            string message = Value.GetAbstractErrorMessage(context);
            Debug.Assert(message != null);

            return BindingHelpers.AddDynamicTestAndDefer(
                call,
                new DynamicMetaObject(
                    Ast.Throw(
                        Ast.New(
                            typeof(ArgumentTypeException).GetConstructor(new Type[] { typeof(string) }),
                            AstUtils.Constant(message)
                        ),
                        typeof(object)
                    ),
                    GetErrorRestrictions(ai)
                ),
                ai.Arguments,
                valInfo
            );
        }
예제 #33
0
 protected InitAdapter(ArgumentValues/*!*/ ai, BinderState/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
 }
예제 #34
0
 private static BindingRestrictions GetInstanceRestriction(ArgumentValues ai) {
     return BindingRestrictions.GetInstanceRestriction(ai.Self.Expression, ai.Self.Value);
 }
예제 #35
0
 public string Get(string argumentName)
 {
     return(ArgumentValues.ContainsKey(argumentName) ? ArgumentValues[argumentName] : null);
 }