Class: Lisp::PrimFrame
Class Method Summary collapse
- .clone_impl(args, env) ⇒ Object
- .get_slot_if_impl(args, env) ⇒ Object
- .get_slot_impl(args, env) ⇒ Object
- .get_super_function(selector, env) ⇒ Object
- .has_slot_impl(args, env) ⇒ Object
- .keys_impl(args, env) ⇒ Object
- .make_frame_impl(args, env) ⇒ Object
- .register ⇒ Object
- .remove_slot_impl(args, env) ⇒ Object
- .send_impl(args, env) ⇒ Object
- .send_super_impl(args, env) ⇒ Object
- .set_slot_impl(args, env) ⇒ Object
Class Method Details
.clone_impl(args, env) ⇒ Object
151 152 153 154 155 |
# File 'lib/rubylisp/prim_frame.rb', line 151 def self.clone_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? frame.clone end |
.get_slot_if_impl(args, env) ⇒ Object
85 86 87 88 89 90 91 |
# File 'lib/rubylisp/prim_frame.rb', line 85 def self.get_slot_if_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? key = args.cadr return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol? frame.get(key) end |
.get_slot_impl(args, env) ⇒ Object
75 76 77 78 79 80 81 82 |
# File 'lib/rubylisp/prim_frame.rb', line 75 def self.get_slot_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? key = args.cadr return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol? return Lisp::Debug.process_error("Frame key (#{key.to_s}) must name an existing slot.", env) unless frame.has_slot?(key) frame.get(key) end |
.get_super_function(selector, env) ⇒ Object
128 129 130 131 132 133 134 135 136 |
# File 'lib/rubylisp/prim_frame.rb', line 128 def self.get_super_function(selector, env) f = env.frame return nil if f.nil? f.parents.each do |p| func = p.get(selector) return func unless func.nil? end nil end |
.has_slot_impl(args, env) ⇒ Object
65 66 67 68 69 70 71 72 |
# File 'lib/rubylisp/prim_frame.rb', line 65 def self.has_slot_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? key = args.cadr return Lisp::Debug.process_error("Frame key must be a symbol but was #{key.type}.", env) unless key.symbol? return Lisp::TRUE if frame.has_slot?(key) Lisp::FALSE end |
.keys_impl(args, env) ⇒ Object
158 159 160 161 162 |
# File 'lib/rubylisp/prim_frame.rb', line 158 def self.keys_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? ConsCell.array_to_list(frame.value.keys) end |
.make_frame_impl(args, env) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/rubylisp/prim_frame.rb', line 49 def self.make_frame_impl(args, env) c = args m = {} while !c.nil? k = c.car return Lisp::Debug.process_error("Slot names must be a symbol, found a {k.type}.", env) unless k.symbol? return Lisp::Debug.process_error("Slot names must end in a colon, found '#{k}'.", env) unless k.naked? v = c.cadr m[k] = v c = c.cddr end Lisp::Frame.with_map(m) end |
.register ⇒ Object
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/rubylisp/prim_frame.rb', line 5 def self.register Primitive.register("make-frame", "*", "(make-frame slot-name slot-value ... )\n\nFrames can be created using the make-frame function, passing it an alternating sequence of slot names and values:\n\n (make-frame a: 1 b: 2)\n\nThis results in a frame with two slots, named a: and b: with values 1 and 2, respectively.") do |args, env| Lisp::PrimFrame::make_frame_impl(args, env) end Primitive.register("has-slot?", "2", "(has-slot? frame slot-name)\n\nThe has-slot? function is used to query whether a frame contains (directly or in an ancestor) the particular slot.") do |args, env| Lisp::PrimFrame::has_slot_impl(args, env) end Primitive.register("get-slot", "2", "(get-slot _frame_ _slot-name_)\n\nThe get-slot function is used to retrieve values from frame slots") do |args, env| Lisp::PrimFrame::get_slot_impl(args, env) end Primitive.register("get-slot-if", "2", "(get-slot-if frame slot-name)\n\nThe same as above, except that if a matching slot is not found, nil is returned instead of raising an error.") do |args, env| Lisp::PrimFrame::get_slot_if_impl(args, env) end Primitive.register("remove-slot!", "2", "(remove-slot! frame slot-name)\n\nThe remove-slot! function is used to function is used to remove a slot from a frame. It only removes slots from the frame itself. not any of it's parents. remove-slot! return #t if the slot was removed, #f otherwise.") do |args, env| Lisp::PrimFrame::remove_slot_impl(args, env) end Primitive.register("set-slot!", "3", "(set-slot! frame slot-name new-value)\n\nThe set-slot! function is used to change values in frame slots") do |args, env| Lisp::PrimFrame::set_slot_impl(args, env) end Primitive.register("send", "*", "(send frame slot-name arg...)\n\nSend the message slot-name to frame, passing along the arg collection. The result is what is returned by the code in that slot.") do |args, env| Lisp::PrimFrame::send_impl(args, env) end Primitive.register("send-super", "*", "**(send-super slot-name arg...)\n\nLike send, but sends to the first parent that has the named slot. send-super can only be used from within a frame.") do |args, env| Lisp::PrimFrame::send_super_impl(args, env) end Primitive.register("clone", "1", "(clone frame)\n\nFrames represent things. For example, you could use a frame that looks like {x: 1 y: 10} to represent a point. A system that would use point frames will typically need many independant points. The approach to this is to create a prototypical point data frame, and use the clone function to create individual, independant frames.") do |args, env| Lisp::PrimFrame::clone_impl(args, env) end Primitive.register("keys", "1", "(keys frame)\n\nReturn a list of the keys in the frame.") do |args, env| Lisp::PrimFrame::keys_impl(args, env) end end |
.remove_slot_impl(args, env) ⇒ Object
94 95 96 97 98 99 100 101 |
# File 'lib/rubylisp/prim_frame.rb', line 94 def self.remove_slot_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? key = args.cadr return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol? return Lisp::TRUE if frame.remove(key) Lisp::FALSE end |
.send_impl(args, env) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/rubylisp/prim_frame.rb', line 114 def self.send_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? selector = args.cadr return Lisp::Debug.process_error("Selector must be a symbol but was #{selector.type}.", env) unless selector.symbol? return Lisp::Debug.process_error("Message sent must name an existing slot in the receiver.", env) unless frame.has_slot?(selector) func = frame.get(selector) return Lisp::Debug.process_error("Message sent must select a function slot but was #{func.type}.", env) unless func.function? params = args.cddr frame_env = Lisp::EnvironmentFrame.extending(env, selector.to_s, frame) frame_env.bind_locally(Symbol.named("self"), frame) func.apply_to(params, frame_env) end |
.send_super_impl(args, env) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rubylisp/prim_frame.rb', line 138 def self.send_super_impl(args, env) return Lisp::Debug.process_error("super can only be used within the context of a frame.", env) unless env.frame selector = args.car return Lisp::Debug.process_error("Selector must be a symbol but was #{selector.type}.", env) unless selector.symbol? func = get_super_function(selector, env) return Lisp::Debug.process_error("Message sent must select a function slot but was #{func.type}.", env) unless func && func.function? params = args.cdr frame_env = Lisp::EnvironmentFrame.extending(env, selector.to_s, env.frame) frame_env.bind_locally(Symbol.named("self"), env.frame) func.apply_to(params, frame_env) end |
.set_slot_impl(args, env) ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'lib/rubylisp/prim_frame.rb', line 104 def self.set_slot_impl(args, env) frame = args.car return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame? key = args.cadr return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol? value = args.caddr frame.at_put(key, value) end |