A context represents a given invocation of a block. (Note this is fairly sketchy at the moment.)
Beispiel #1
0
        /// <summary>
        /// Initializes the context.
        /// </summary>
        /// <param name="StaticCodeObject"></param>
        /// <param name="Caller"></param>
        public Context(RakudoObject StaticCodeObject_Uncast, Context Caller, RakudoObject Capture)
        {
            // Set up static code object and caller pointers.
            var StaticCodeObject = (RakudoCodeRef.Instance)StaticCodeObject_Uncast;
            this.StaticCodeObject = StaticCodeObject;
            this.Caller = Caller;
            this.Capture = Capture;

            // Static sub object should have this as the current
            // context.
            StaticCodeObject.CurrentContext = this;

            // Lex pad should be an "instantiation" of the static one.
            // Instantiating a lexpad creates a new dynamic instance of it
            // from a static one, copying over the slot storage entries
            // from the static one but sharing the slot mapping.
            this.LexPad.SlotMapping = StaticCodeObject.StaticLexPad.SlotMapping;
            this.LexPad.Storage = (RakudoObject[])StaticCodeObject.StaticLexPad.Storage.Clone();

            // Set outer context.
            if (StaticCodeObject.OuterForNextInvocation != null)
            {
                this.Outer = StaticCodeObject.OuterForNextInvocation;
            }
            else if (StaticCodeObject.OuterBlock.CurrentContext != null)
            {
                this.Outer = StaticCodeObject.OuterBlock.CurrentContext;
            }
            else
            {
                // Auto-close. In this we go setting up fake contexts
                // that use the static lexpad until we find a real one.
                var CurContext = this;
                var OuterBlock = StaticCodeObject.OuterBlock;
                while (OuterBlock != null)
                {
                    // If we found a block with a context, we're done.
                    if (OuterBlock.CurrentContext != null)
                    {
                        CurContext.Outer = OuterBlock.CurrentContext;
                        break;
                    }

                    // Build the fake context.
                    var OuterContext = new Context();
                    OuterContext.StaticCodeObject = OuterBlock;
                    OuterContext.LexPad = OuterBlock.StaticLexPad;

                    // Link it.
                    CurContext.Outer = OuterContext;

                    // Step back one level.
                    CurContext = OuterContext;
                    OuterBlock = OuterBlock.OuterBlock;
                }
            }
        }
Beispiel #2
0
 /// <summary>
 /// Sets up the bootstrapping setting that we use to compile the
 /// real setting.
 /// </summary>
 /// <param name="KnowHOW"></param>
 /// <returns></returns>
 private static Context BootstrapSetting(RakudoObject KnowHOW, RakudoObject KnowHOWAttribute)
 {
     var SettingContext = new Context();
     SettingContext.LexPad = new Lexpad(new string[]
         { "KnowHOW", "KnowHOWAttribute", "capture", "NQPInt", "NQPNum", "NQPStr", "NQPList", "NQPCode", "list", "NQPArray", "NQPHash" });
     SettingContext.LexPad.Storage = new RakudoObject[]
         {
             KnowHOW,
             KnowHOWAttribute,
             REPRRegistry.get_REPR_by_name("P6capture").type_object_for(null, null),
             REPRRegistry.get_REPR_by_name("P6int").type_object_for(null, null),
             REPRRegistry.get_REPR_by_name("P6num").type_object_for(null, null),
             REPRRegistry.get_REPR_by_name("P6str").type_object_for(null, null),
             REPRRegistry.get_REPR_by_name("P6list").type_object_for(null, null),
             REPRRegistry.get_REPR_by_name("RakudoCodeRef").type_object_for(null, KnowHOW.STable.REPR.instance_of(null, KnowHOW)),
             CodeObjectUtility.WrapNativeMethod((TC, self, C) =>
                 {
                     var NQPList = Ops.get_lex(TC, "NQPList");
                     var List = NQPList.STable.REPR.instance_of(TC, NQPList) as P6list.Instance;
                     var NativeCapture = C as P6capture.Instance;
                     foreach (var Obj in NativeCapture.Positionals)
                         List.Storage.Add(Obj);
                     return List;
                 }),
             null,
             null
         };
     return SettingContext;
 }
Beispiel #3
0
        /// <summary>
        /// Binds the capture against the given signature and stores the
        /// bound values into variables in the lexpad.
        /// 
        /// XXX No type-checking is available just yet. :-(
        /// 
        /// XXX No support for nameds mapping to positionals yet either.
        /// 
        /// (In other words, this kinda sucks...)
        /// </summary>
        /// <param name="C"></param>
        /// <param name="Capture"></param>
        public static void Bind(ThreadContext TC, Context C, RakudoObject Capture)
        {
            // Make sure the object is really a low level capture (don't handle
            // otherwise yet) and grab the pieces.
            var NativeCapture = Capture as P6capture.Instance;
            if (NativeCapture == null)
                throw new NotImplementedException("Can only deal with native captures at the moment");
            var Positionals = NativeCapture.Positionals ?? EmptyPos;
            var Nameds = NativeCapture.Nameds ?? EmptyNamed;
            Dictionary<string, bool> SeenNames = null;

            // See if we have to do any flattening.
            if (NativeCapture.FlattenSpec != null)
                Flatten(NativeCapture.FlattenSpec, ref Positionals, ref Nameds);

            // If we have no signature, that's same as an empty signature.
            var Sig = C.StaticCodeObject.Sig;
            if (Sig == null)
                return;

            // Current positional.
            var CurPositional = 0;

            // Iterate over the parameters.
            var Params = Sig.Parameters;
            var NumParams = Params.Length;
            for (int i = 0; i < NumParams; i++)
            {
                var Param = Params[i];

                // Positional required?
                if (Param.Flags == Parameter.POS_FLAG)
                {
                    if (CurPositional < Positionals.Length)
                    {
                        // We have an argument, just bind it.
                        C.LexPad.Storage[Param.VariableLexpadPosition] = Positionals[CurPositional];
                    }
                    else
                    {
                        throw new Exception("Not enough positional parameters; got " +
                            CurPositional.ToString() + " but needed " +
                            NumRequiredPositionals(C.StaticCodeObject.Sig).ToString());
                    }

                    // Increment positional counter.
                    CurPositional++;
                }

                // Positional optional?
                else if (Param.Flags == Parameter.OPTIONAL_FLAG)
                {
                    if (CurPositional < Positionals.Length)
                    {
                        // We have an argument, just bind it.
                        C.LexPad.Storage[Param.VariableLexpadPosition] = Positionals[CurPositional];
                        CurPositional++;
                    }
                    else
                    {
                        // Default value, vivification.
                        // ((RakudoCodeRef.Instance)Param.DefaultValue).CurrentContext = TC.CurrentContext;
                        C.LexPad.Storage[Param.VariableLexpadPosition] = Param.DefaultValue.STable.Invoke(TC, Param.DefaultValue, Capture);
                    }
                }

                // Named slurpy?
                else if ((Param.Flags & Parameter.NAMED_SLURPY_FLAG) != 0)
                {
                    var SlurpyHolder = TC.DefaultHashType.STable.REPR.instance_of(TC, TC.DefaultHashType);
                    C.LexPad.Storage[Param.VariableLexpadPosition] = SlurpyHolder;
                    foreach (var Name in Nameds.Keys)
                        if (SeenNames == null || !SeenNames.ContainsKey(Name))
                            Ops.llmapping_bind_at_key(TC, SlurpyHolder,
                                Ops.box_str(TC, Name, TC.DefaultStrBoxType),
                                Nameds[Name]);
                }

                // Positional slurpy?
                else if ((Param.Flags & Parameter.POS_SLURPY_FLAG) != 0)
                {
                    var SlurpyHolder = TC.DefaultArrayType.STable.REPR.instance_of(TC, TC.DefaultArrayType);
                    C.LexPad.Storage[Param.VariableLexpadPosition] = SlurpyHolder;
                    int j;
                    for (j = CurPositional; j < Positionals.Length; j++)
                        Ops.lllist_push(TC, SlurpyHolder, Positionals[j]);
                    CurPositional = j;
                }

                // Named?
                else if (Param.Name != null)
                {
                    // Yes, try and get argument.
                    RakudoObject Value;
                    if (Nameds.TryGetValue(Param.Name, out Value))
                    {
                        // We have an argument, just bind it.
                        C.LexPad.Storage[Param.VariableLexpadPosition] = Value;
                        if (SeenNames == null)
                            SeenNames = new Dictionary<string, bool>();
                        SeenNames.Add(Param.Name, true);
                    }
                    else
                    {
                        // Optional?
                        if ((Param.Flags & Parameter.OPTIONAL_FLAG) == 0)
                        {
                            throw new Exception("Required named parameter " + Param.Name + " missing");
                        }
                        else
                        {
                            C.LexPad.Storage[Param.VariableLexpadPosition] = Param.DefaultValue.STable.Invoke(TC, Param.DefaultValue, Capture);
                        }
                    }
                }

                // Otherwise, WTF?
                else
                {

                }
            }

            // Ensure we had enough positionals.
            var PossiesInCapture = Positionals.Length;
            if (CurPositional > PossiesInCapture)
                throw new Exception("Too many positional arguments passed; expected " +
                    NumRequiredPositionals(C.StaticCodeObject.Sig).ToString() +
                    " but got " + PossiesInCapture.ToString());

            // XXX TODO; Ensure we don't have leftover nameds.
        }