public Instance(SharedTable STable) { this.STable = STable; }
/// <summary> /// Creates a type object that references the given HOW and /// this REPR; note we just use the singleton instance for /// all of them, since the REPR stores nothing distinct. /// </summary> /// <param name="HOW"></param> /// <returns></returns> public override RakudoObject type_object_for(ThreadContext TC, RakudoObject MetaPackage) { var STable = new SharedTable(); STable.HOW = MetaPackage; STable.REPR = this; STable.WHAT = new Instance(STable); return STable.WHAT; }
/// <summary> /// Bootstraps the KnowHOW. This is were things "bottom out" in the /// meta-model so it's a tad loopy. Basically, we create a KnowHOW /// type object. We then create an instance from that and add a /// bunch of methods to it. However, we also give it a special /// STable with FindMethod overridden in it to go looking right /// into the methods dictionary. /// </summary> /// <returns></returns> public static RakudoObject Bootstrap() { // Create our KnowHOW type object. Note we don't have a HOW // just yet, so pass in null. var REPR = REPRRegistry.get_REPR_by_name("KnowHOWREPR"); var KnowHOW = REPR.type_object_for(null, null); // We'll set up a dictionary of our various methods to go into // KnowHOW's HOW, since we'll want to work with them a bit. var KnowHOWMeths = new Dictionary<string, RakudoObject>(); KnowHOWMeths.Add("new_type", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // We first create a new HOW instance. var KnowHOWTypeObj = CaptureHelper.GetPositional(Cap, 0); var HOW = KnowHOWTypeObj.STable.REPR.instance_of(TC, KnowHOWTypeObj.STable.WHAT); // If we have a name arg, stash that value away. var TypeName = CaptureHelper.GetNamed(Cap, "name"); (HOW as KnowHOWREPR.KnowHOWInstance).Name = TypeName ?? Ops.box_str(TC, "<anon>"); // Now create a new type object to go with it of the // desired REPR; we default to P6opaque (note that the // KnowHOW repr only knows how to store a table of // methods and attributes, it can't be used for an // instance object that actually wants to store some // instance data). var REPRName = CaptureHelper.GetNamed(Cap, "repr"); if (REPRName != null) { // Look up the REPR. var REPRToUse = REPRRegistry.get_REPR_by_name(Ops.unbox_str(null, REPRName)); return REPRToUse.type_object_for(null, HOW); } else { // Just go with the P6opaque REPR. return REPRRegistry.get_REPR_by_name("P6opaque").type_object_for(TC, HOW); } })); KnowHOWMeths.Add("add_attribute", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { var HOW = (KnowHOWREPR.KnowHOWInstance)CaptureHelper.GetPositional(Cap, 0); var Attr = CaptureHelper.GetPositional(Cap, 2); HOW.Attributes.Add(Attr); return CaptureHelper.Nil(); })); KnowHOWMeths.Add("add_method", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { var HOW = (KnowHOWREPR.KnowHOWInstance)CaptureHelper.GetPositional(Cap, 0); var Name = CaptureHelper.GetPositionalAsString(Cap, 2); var Method = CaptureHelper.GetPositional(Cap, 3); HOW.Methods.Add(Name, Method); return CaptureHelper.Nil(); })); KnowHOWMeths.Add("find_method", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // We go to some effort to be really fast in here, 'cus it's a // hot path for dynamic dispatches. var Positionals = (Cap as P6capture.Instance).Positionals; var HOW = Positionals[0] as KnowHOWREPR.KnowHOWInstance; RakudoObject Method; if (HOW.Methods.TryGetValue(Ops.unbox_str(TC, Positionals[2]), out Method)) return Method; else throw new InvalidOperationException(string.Format( "No method '{0}' found in knowhow '{1}'", Ops.unbox_str(TC, Positionals[2]), Ops.unbox_str(TC, HOW.Name))); })); KnowHOWMeths.Add("compose", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { var Obj = CaptureHelper.GetPositional(Cap, 1); return Obj; })); KnowHOWMeths.Add("attributes", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // Safe to just return a P6list instance that points at // the same thing we hold internally, since a list is // immutable. However, if default list type has no HOW, // we will see if we can find one that does have it. var HOW = (KnowHOWREPR.KnowHOWInstance)CaptureHelper.GetPositional(Cap, 0); var ListType = MostDefinedListType(TC); var Result = ListType.STable.REPR.instance_of(TC, ListType); ((P6list.Instance)Result).Storage = HOW.Attributes; return Result; })); KnowHOWMeths.Add("methods", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // Return the methods list. var HOW = (KnowHOWREPR.KnowHOWInstance)CaptureHelper.GetPositional(Cap, 0); var ListType = MostDefinedListType(TC); var Result = ListType.STable.REPR.instance_of(TC, ListType); ((P6list.Instance)Result).Storage.AddRange(HOW.Methods.Values); return Result; })); KnowHOWMeths.Add("parents", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // A pure prototype never has any parents, so return an empty list. var ListType = MostDefinedListType(TC); return ListType.STable.REPR.instance_of(TC, ListType); })); KnowHOWMeths.Add("type_check", CodeObjectUtility.WrapNativeMethod((TC, Ignored, Cap) => { // Can only match against ourselves. var self = CaptureHelper.GetPositional(Cap, 1); var check = CaptureHelper.GetPositional(Cap, 2); return Ops.box_int(TC, self.STable.WHAT == check.STable.WHAT ? 1 : 0, TC.DefaultBoolBoxType); })); // We create a KnowHOW instance that can describe itself. This // means .HOW.HOW.HOW.HOW etc will always return that, which // closes the model up. var KnowHOWHOW = (KnowHOWREPR.KnowHOWInstance)REPR.instance_of(null, KnowHOW); foreach (var Method in KnowHOWMeths) KnowHOWHOW.Methods.Add(Method.Key, Method.Value); // We need to clone the STable. var STableCopy = new SharedTable(); STableCopy.HOW = KnowHOWHOW; STableCopy.WHAT = KnowHOW.STable.WHAT; STableCopy.REPR = KnowHOW.STable.REPR; KnowHOWHOW.STable = STableCopy; // And put a fake FindMethod in there that just looks in the // dictionary. KnowHOWHOW.STable.SpecialFindMethod = (TC, Obj, Name, Hint) => { var MTable = ((KnowHOWREPR.KnowHOWInstance)Obj).Methods; if (MTable.ContainsKey(Name)) return MTable[Name]; else throw new InvalidOperationException("No such method " + Name); }; // Set this as the KnowHOW's HOW. KnowHOW.STable.HOW = KnowHOWHOW; // And we should be done. return KnowHOW; }
/// <summary> /// Create a new type object. /// </summary> /// <param name="MetaPackage"></param> /// <returns></returns> public override RakudoObject type_object_for(ThreadContext TC, RakudoObject MetaPackage) { // Do the usual bits of setup for the type-object. var STable = new SharedTable(); STable.HOW = MetaPackage; STable.REPR = this; STable.WHAT = new Instance(STable); // Also twiddle the S-Table's Invoke to invoke the contained // function. STable.SpecialInvoke = (TCi, Obj, Cap) => ((RakudoCodeRef.Instance)Obj).Body(TCi, Obj, Cap); return STable.WHAT; }
public KnowHOWInstance(SharedTable STable) { this.STable = STable; }
/// <summary> /// Gets a type object pointing to the given HOW. /// </summary> /// <param name="HOW"></param> /// <returns></returns> public override RakudoObject type_object_for(ThreadContext TC, RakudoObject HOW) { var STable = new SharedTable(); STable.HOW = HOW; STable.REPR = this; STable.WHAT = new KnowHOWInstance(STable); return STable.WHAT; }