Class: Lisp::Assignment

Inherits:
Object show all
Defined in:
lib/rubylisp/assignment.rb

Class Method Summary collapse

Class Method Details

.registerObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/rubylisp/assignment.rb', line 5

def self.register
  Primitive.register("set!", "(set! _name_ _new-value_)\n\nThe way to assign (i.e. rebind) a symbol. `name` is the symbol to be rebound.
The `new-value` sexpr is evaluated to arrive at the new value to be bound to. Use of `set!` is frowned upon, and should not be used without thought.") do |args, env|
    Lisp::Assignment::setbang_impl(args, env)
  end
  
  Primitive.register("set-car!", "(set-car! _cons-cell_ _new-value_)\n\nSet the `car` pointer of `cons-cell`.") do |args, env|
    Lisp::Assignment::setcarbang_impl(args, env)
  end
  
  Primitive.register("set-cdr!", "(set-cdr! _cons-cell_ _new-value_)\n\nSet the `cdr` pointer of `cons-cell`.") do |args, env|
    Lisp::Assignment::setcdrbang_impl(args, env)
  end
  
  Primitive.register("set-nth!", "(set-nth! _n_ _list-or-vector_ _new-value_)\n\nSets the `n`th element of `list-or-vector` to `new-value`.") do |args, env|
    Lisp::Assignment::setnthbang_impl(args, env)
  end
  
end

.setbang_impl(args, env) ⇒ Object



26
27
28
29
30
31
# File 'lib/rubylisp/assignment.rb', line 26

def self.setbang_impl(args, env)
  sym = args.car
  return Lisp::Debug.process_error("set! requires a raw (unevaluated) symbol as it's first argument.", env) unless sym.symbol?
  value = args.cadr.evaluate(env)
  env.set(sym, value)
end

.setcarbang_impl(args, env) ⇒ Object



34
35
36
37
38
39
# File 'lib/rubylisp/assignment.rb', line 34

def self.setcarbang_impl(args, env)
  pair = args.car.evaluate(env)
  return Lisp::Debug.process_error("set-car! requires a pair as it's first argument.", env) unless pair.pair?
  value = args.cadr.evaluate(env)
  pair.set_car!(value)
end

.setcdrbang_impl(args, env) ⇒ Object



42
43
44
45
46
47
# File 'lib/rubylisp/assignment.rb', line 42

def self.setcdrbang_impl(args, env)
  pair = args.car.evaluate(env)
  return Lisp::Debug.process_error("set-cdr! requires a pair as it's first argument.", env) unless pair.pair?
  value = args.cadr.evaluate(env)
  pair.set_cdr!(value)
end

.setnthbang_impl(args, env) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/rubylisp/assignment.rb', line 50

def self.setnthbang_impl(args, env)
  return Lisp::Debug.process_error("set-nth! requires 3 arguments.", env) unless args.length == 3
  n = args.car.evaluate(env)
  return Lisp::Debug.process_error("The first argument of set-nth! has to be an number.", env) unless n.number?
  return Lisp::Debug.process_error("The first argument of set-nth! has to be positive.", env) unless n.value > 0

  l = args.cadr.evaluate(env)
  return Lisp::Debug.process_error("set-nth! requires a list or vector as it's first argument.", env) unless l.list? || l.vector?
  value = args.caddr.evaluate(env)
  l.set_nth!(n.value, value)
  l
end