class Lisp::PrimFrame

Public Class Methods

clone_impl(args, env) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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() click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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