rubylisp 0.2.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +129 -2
  3. data/bin/rubylisp +87 -12
  4. data/lib/rubylisp/atom.rb +25 -6
  5. data/lib/rubylisp/boolean.rb +9 -6
  6. data/lib/rubylisp/builtins.rb +19 -18
  7. data/lib/rubylisp/character.rb +14 -275
  8. data/lib/rubylisp/class_object.rb +56 -0
  9. data/lib/rubylisp/cons_cell.rb +56 -25
  10. data/lib/rubylisp/debug.rb +15 -19
  11. data/lib/rubylisp/environment.rb +27 -0
  12. data/lib/rubylisp/environment_frame.rb +31 -6
  13. data/lib/rubylisp/eof_object.rb +26 -0
  14. data/lib/rubylisp/exception.rb +61 -61
  15. data/lib/rubylisp/ext.rb +32 -6
  16. data/lib/rubylisp/ffi_new.rb +2 -1
  17. data/lib/rubylisp/ffi_send.rb +15 -5
  18. data/lib/rubylisp/frame.rb +5 -164
  19. data/lib/rubylisp/function.rb +4 -3
  20. data/lib/rubylisp/macro.rb +13 -8
  21. data/lib/rubylisp/{object.rb → native_object.rb} +0 -15
  22. data/lib/rubylisp/number.rb +5 -0
  23. data/lib/rubylisp/parser.rb +81 -52
  24. data/lib/rubylisp/port.rb +27 -0
  25. data/lib/rubylisp/prim_alist.rb +115 -0
  26. data/lib/rubylisp/prim_assignment.rb +61 -0
  27. data/lib/rubylisp/prim_character.rb +273 -0
  28. data/lib/rubylisp/{ffi_class.rb → prim_class_object.rb} +16 -69
  29. data/lib/rubylisp/prim_environment.rb +203 -0
  30. data/lib/rubylisp/prim_equivalence.rb +93 -0
  31. data/lib/rubylisp/prim_frame.rb +166 -0
  32. data/lib/rubylisp/prim_io.rb +266 -0
  33. data/lib/rubylisp/prim_list_support.rb +496 -0
  34. data/lib/rubylisp/{logical.rb → prim_logical.rb} +9 -14
  35. data/lib/rubylisp/prim_math.rb +397 -0
  36. data/lib/rubylisp/prim_native_object.rb +21 -0
  37. data/lib/rubylisp/prim_relational.rb +42 -0
  38. data/lib/rubylisp/{special_forms.rb → prim_special_forms.rb} +98 -85
  39. data/lib/rubylisp/prim_string.rb +792 -0
  40. data/lib/rubylisp/prim_system.rb +55 -0
  41. data/lib/rubylisp/prim_type_checks.rb +58 -0
  42. data/lib/rubylisp/prim_vector.rb +497 -0
  43. data/lib/rubylisp/primitive.rb +51 -6
  44. data/lib/rubylisp/string.rb +4 -803
  45. data/lib/rubylisp/symbol.rb +0 -1
  46. data/lib/rubylisp/tokenizer.rb +161 -137
  47. data/lib/rubylisp/vector.rb +10 -31
  48. data/lib/rubylisp.rb +1 -0
  49. metadata +46 -17
  50. data/lib/rubylisp/alist.rb +0 -230
  51. data/lib/rubylisp/assignment.rb +0 -65
  52. data/lib/rubylisp/equivalence.rb +0 -118
  53. data/lib/rubylisp/io.rb +0 -74
  54. data/lib/rubylisp/list_support.rb +0 -526
  55. data/lib/rubylisp/math.rb +0 -405
  56. data/lib/rubylisp/relational.rb +0 -46
  57. data/lib/rubylisp/system.rb +0 -20
  58. data/lib/rubylisp/testing.rb +0 -136
  59. data/lib/rubylisp/type_checks.rb +0 -60
@@ -2,31 +2,50 @@ module Lisp
2
2
 
3
3
  class EnvironmentFrame
4
4
 
5
- attr_accessor :frame, :current_code, :previous
5
+ attr_accessor :frame, :current_code, :previous, :name
6
+ attr_reader :parent, :project_environment
6
7
 
7
8
  def self.global
8
- @@global_frame ||= EnvironmentFrame.new(nil)
9
+ @@global_frame ||= EnvironmentFrame.new(nil, "GLOBAL")
9
10
  @@global_frame
10
11
  end
11
12
 
12
- def self.extending(parent, f=nil)
13
+ def self.extending(parent, name, f=nil)
13
14
  f ||= parent.frame if parent && parent.has_frame?
14
- self.new(parent, f)
15
+ e = self.new(parent, name, f)
16
+ TopLevelEnvironments[name] = e if parent.nil? || parent == self.global
17
+ e
15
18
  end
16
19
 
17
- def initialize(parent, f=nil)
20
+ def initialize(parent, name, f=nil)
18
21
  @bindings = []
19
22
  @parent = parent
23
+ @name = name
20
24
  @frame = f
21
25
  @current_code = []
22
26
  end
23
27
 
28
+
29
+ def clear
30
+ TopLevelEnvironments[@name] = nil if TopLevelEnvironments.has_key?(@name)
31
+ @bindings.each {|b| b.value = nil}
32
+ end
33
+
34
+
24
35
  def has_frame?
25
36
  !@frame.nil?
26
37
  end
27
38
 
28
39
  # Bindings following parent env frame pointer
29
40
 
41
+ def bound_names
42
+ @bindings.map {|b| b.symbol}
43
+ end
44
+
45
+ def bound_values
46
+ @bindings.map {|b| b.value}
47
+ end
48
+
30
49
  def is_name_bound?(str)
31
50
  if !@frame && @frame.has_slot?(Lisp:Symbol.named("#{str}:", true))
32
51
  return true
@@ -38,6 +57,11 @@ module Lisp
38
57
  return @parent.is_name_bound?(str)
39
58
  end
40
59
 
60
+ def name_bound_locally?(str)
61
+ binding = @bindings.detect {|b| b.symbol.name == str}
62
+ !binding.nil?
63
+ end
64
+
41
65
  def binding_for(symbol)
42
66
  binding = @bindings.detect {|b| b.symbol.name == symbol.name}
43
67
  return binding unless binding.nil?
@@ -152,8 +176,9 @@ module Lisp
152
176
  1 + @previous.depth
153
177
  end
154
178
  end
155
-
179
+
156
180
  end
157
181
 
182
+ TopLevelEnvironments = {}
158
183
 
159
184
  end
@@ -0,0 +1,26 @@
1
+ module Lisp
2
+
3
+ class EofObject < Atom
4
+
5
+ def self.instance
6
+ @instance ||= self.new()
7
+ end
8
+
9
+ def initialize()
10
+ end
11
+
12
+ def type
13
+ :eof_object
14
+ end
15
+
16
+ def eof_object?
17
+ true
18
+ end
19
+
20
+ def to_s
21
+ "<EOF>"
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -3,81 +3,81 @@ module Lisp
3
3
  class Exception
4
4
 
5
5
  def self.register
6
- Primitive.register("raise") {|args, env| Lisp::Exception::raise_impl(args, env) }
7
- Primitive.register("reraise") {|args, env| Lisp::Exception::reraise_impl(args, env) }
8
- Primitive.register("try") {|args, env| Lisp::Exception::try_impl(args, env) }
9
- Primitive.register("reraise") {|args, env| Lisp::Exception::reraise_impl(args, env) }
10
- Primitive.register("resume") {|args, env| Lisp::Exception::resume_impl(args, env) }
11
- Primitive.register("restart") {|args, env| Lisp::Exception::restart_impl(args, env) }
6
+ # Primitive.register("raise") {|args, env| Lisp::Exception::raise_impl(args, env) }
7
+ # Primitive.register("reraise") {|args, env| Lisp::Exception::reraise_impl(args, env) }
8
+ # Primitive.register("try") {|args, env| Lisp::Exception::try_impl(args, env) }
9
+ # Primitive.register("reraise") {|args, env| Lisp::Exception::reraise_impl(args, env) }
10
+ # Primitive.register("resume") {|args, env| Lisp::Exception::resume_impl(args, env) }
11
+ # Primitive.register("restart") {|args, env| Lisp::Exception::restart_impl(args, env) }
12
12
  end
13
13
 
14
14
 
15
- def handler_or_nil(handlers, exception_name)
16
- handlers.each do |handler_pair|
17
- exceptions = handler_pair.car
18
- if exceptions.eq(exception_name) || (exceptions.pair? && exceptions.include?(exception_name))
19
- handler_pair.cdr
20
- else
21
- nil
22
- end
23
- end
24
- end
25
-
26
- def self.do_exception(name, with_message, args, env)
27
- frame = env
28
- while !frame.nil?
29
- handlers = frame.value_of(Symbol.named("__handlers__"))
30
- unless handlers.nil?
31
- handler = handler_or_nil(handlers, for: name)
32
- unless handler.nil?
33
- handler.apply_to_without_evaluating(args, frame)
34
- break
35
- end
36
- end
37
- frame = frame.parent
38
- if frame.nil?
39
- exception_message = message.empty? ? "" : ": #{message}"
40
- return Lisp::Debug.process_error("Unhandled Exception: #{exception_name}#{exception_message}", env)
41
- end
42
- end
43
- end
15
+ # def handler_or_nil(handlers, exception_name)
16
+ # handlers.each do |handler_pair|
17
+ # exceptions = handler_pair.car
18
+ # if exceptions.eq(exception_name) || (exceptions.pair? && exceptions.include?(exception_name))
19
+ # handler_pair.cdr
20
+ # else
21
+ # nil
22
+ # end
23
+ # end
24
+ # end
25
+
26
+ # def self.do_exception(name, with_message, args, env)
27
+ # frame = env
28
+ # while !frame.nil?
29
+ # handlers = frame.value_of(Symbol.named("__handlers__"))
30
+ # unless handlers.nil?
31
+ # handler = handler_or_nil(handlers, for: name)
32
+ # unless handler.nil?
33
+ # handler.apply_to_without_evaluating(args, frame)
34
+ # break
35
+ # end
36
+ # end
37
+ # frame = frame.parent
38
+ # if frame.nil?
39
+ # exception_message = message.empty? ? "" : ": #{message}"
40
+ # return Lisp::Debug.process_error("Unhandled Exception: #{exception_name}#{exception_message}", env)
41
+ # end
42
+ # end
43
+ # end
44
44
 
45
45
  def self.raise_impl(args, env)
46
- return Lisp::Debug.process_error("'raise' requires at least one argument.", env) unless args.length > 0
47
- exception_name = args.car.evaluate(env)
48
- return Lisp::Debug.process_error("'raise' requires an exception name as it's first argument.", env) unless exception_name.string? || class_name.symbol?
46
+ # return Lisp::Debug.process_error("'raise' requires at least one argument.", env) unless args.length > 0
47
+ # exception_name = args.car.evaluate(env)
48
+ # return Lisp::Debug.process_error("'raise' requires an exception name as it's first argument.", env) unless exception_name.string? || class_name.symbol?
49
49
 
50
- message = ""
51
- if args.length > 1
52
- message = args.cadr.evaluate(env)
53
- return Lisp::Debug.process_error("The message parameter to 'raise' must be a string.", env) unless message.string?
54
- end
50
+ # message = ""
51
+ # if args.length > 1
52
+ # message = args.cadr.evaluate(env)
53
+ # return Lisp::Debug.process_error("The message parameter to 'raise' must be a string.", env) unless message.string?
54
+ # end
55
55
 
56
- handler_args = args.length > 2 ? Lisp::ConsCell.array_to_list(args.cdr.to_a.collect {|a| a.evaluate(env)}) : Lisp::ConsCell.new
56
+ # handler_args = args.length > 2 ? Lisp::ConsCell.array_to_list(args.cdr.to_a.collect {|a| a.evaluate(env)}) : Lisp::ConsCell.new
57
57
  end
58
58
 
59
59
 
60
60
  def self.try_impl(args, env)
61
- raw_handlers = args.car
62
- body = args.cdr
61
+ # raw_handlers = args.car
62
+ # body = args.cdr
63
63
 
64
- return Lisp::Debug.process_error("Exception handlers must be a list.", env) unless raw_handlers.list?
65
- return Lisp::Debug.process_error("Exception handlers must be a list of pairs.", env) unless raw_handlers.all? {|h| h.list?}
66
- return Lisp::Debug.process_error("Exception clause must be a symbol/string or a list of symbol/string.", env) unless raw_handlers.all? do |h|
67
- ex = h.car
68
- ex.symbol? || ex.string? || (ex.list? && ex.all? {|h2| h2.symbol? || h2.string?})
69
- end
64
+ # return Lisp::Debug.process_error("Exception handlers must be a list.", env) unless raw_handlers.list?
65
+ # return Lisp::Debug.process_error("Exception handlers must be a list of pairs.", env) unless raw_handlers.all? {|h| h.list?}
66
+ # return Lisp::Debug.process_error("Exception clause must be a symbol/string or a list of symbol/string.", env) unless raw_handlers.all? do |h|
67
+ # ex = h.car
68
+ # ex.symbol? || ex.string? || (ex.list? && ex.all? {|h2| h2.symbol? || h2.string?})
69
+ # end
70
70
 
71
- array_of_handlers = raw_handlers.to_a.collect do |h|
72
- ex = h.car
73
- f = h.cadr.evaluate(env)
74
- return Lisp::Debug.process_error("Exception handler has to be a function.", env) unless f.function?
75
- Lisp::ConsCell.cons(ex, f)
76
- end
77
- handlers = Lisp::ConsCell.array_to_list(array_of_handlers)
78
- env.bind_locally(Symbol.named("__handlers__"), handlers)
71
+ # array_of_handlers = raw_handlers.to_a.collect do |h|
72
+ # ex = h.car
73
+ # f = h.cadr.evaluate(env)
74
+ # return Lisp::Debug.process_error("Exception handler has to be a function.", env) unless f.function?
75
+ # Lisp::ConsCell.cons(ex, f)
76
+ # end
77
+ # handlers = Lisp::ConsCell.array_to_list(array_of_handlers)
78
+ # env.bind_locally(Symbol.named("__handlers__"), handlers)
79
79
 
80
- body.evaluate_each(env)
80
+ # body.evaluate_each(env)
81
81
  end
82
82
 
83
83
 
data/lib/rubylisp/ext.rb CHANGED
@@ -5,15 +5,29 @@ class NilClass
5
5
  end
6
6
 
7
7
  def false?
8
- true
8
+ false
9
9
  end
10
10
 
11
11
  def to_s
12
12
  "()"
13
13
  end
14
14
 
15
+
16
+ def to_ary
17
+ []
18
+ end
19
+
20
+
21
+ def eqv?(other)
22
+ other.nil? || (other.pair? && other.empty?)
23
+ end
24
+
15
25
  def eq?(other)
16
- other.nil?
26
+ other.nil? || (other.pair? && other.empty?)
27
+ end
28
+
29
+ def equal?(other)
30
+ other.nil? || (other.pair? && other.empty?)
17
31
  end
18
32
 
19
33
  def print_string
@@ -84,14 +98,25 @@ class NilClass
84
98
  true
85
99
  end
86
100
 
101
+ def vector?
102
+ false
103
+ end
104
+
105
+ def environment?
106
+ false
107
+ end
108
+
87
109
  def method_missing(name, *args, &block)
88
- if name[0] == ?c && name[-1] == ?r && (name[1..-2].chars.all? {|e| "ad".include?(e)})
110
+ is_list_walk = name[0] == ?c && name[-1] == ?r && (name[1..-2].chars.all? {|e| "ad".include?(e)})
111
+ if is_list_walk
89
112
  nil
90
113
  else
114
+ #puts "nil#method_missing name: #{name} args #{args}"
115
+ #puts caller
91
116
  super
92
117
  end
93
118
  end
94
-
119
+
95
120
  def primitive?
96
121
  false
97
122
  end
@@ -112,8 +137,9 @@ class NilClass
112
137
  true
113
138
  end
114
139
 
115
-
116
-
140
+ def flatten
141
+ nil
142
+ end
117
143
  end
118
144
 
119
145
 
@@ -4,14 +4,15 @@ module Lisp
4
4
 
5
5
  def initialize(name)
6
6
  @value = name
7
- @klass = Object.const_get(name)
8
7
  end
9
8
 
10
9
  def apply_to(args, env)
10
+ @klass = Object.const_get(@value)
11
11
  NativeObject.with_value(@klass.new)
12
12
  end
13
13
 
14
14
  def apply_to_without_evaluating(args, env)
15
+ @klass = Object.const_get(@value)
15
16
  NativeObject.with_value(@klass.new)
16
17
  end
17
18
 
@@ -10,7 +10,9 @@ module Lisp
10
10
  apply_to_without_evaluating(Lisp::ConsCell.array_to_list(args.to_a.map {|a| a.evaluate(env)}), env)
11
11
  end
12
12
 
13
+ # convert a rubymotion arg to a lisp arg
13
14
  def convert_value(value)
15
+ #puts "convert_value(#{value.to_s})\n"
14
16
  case value.class.name
15
17
  when "Fixnum", "Float"
16
18
  Lisp::Number.with_value(value)
@@ -30,11 +32,17 @@ module Lisp
30
32
  end
31
33
 
32
34
 
35
+ # convert a lisp arg to a rubymotion arg
33
36
  def process_arg(a, env)
37
+ #puts "process_arg(#{a.to_s})"
34
38
  if a.function?
35
- proc do |*args|
36
- arg_list = args.empty? ? nil : Lisp::ConsCell.array_to_list(args.collect {|arg| convert_value(arg) })
37
- a.apply_to(arg_list, env)
39
+ #puts "function arg"
40
+ proc do #|*args|
41
+ #puts "Proc argument invoked"
42
+ # arg_list = args.empty? ? nil : Lisp::ConsCell.array_to_list(args.collect {|arg| convert_value(arg) })
43
+ # puts "Applying #{@a.to_s} to #{arg_list}"
44
+
45
+ a.apply_to(nil, env)
38
46
  end
39
47
  elsif a.list?
40
48
  a.to_a.map {|i| process_arg(i, env)}
@@ -49,6 +57,8 @@ module Lisp
49
57
  return Lisp::Debug.process_error("Send target of '#{@value}' evaluated to nil.", env) if target.nil?
50
58
  return Lisp::Debug.process_error("Target of an FFI send of '#{@value}' must be a wrapped ObjC object, was #{target}", env) unless target.object?
51
59
 
60
+ # puts "Sending #{@value} to #{target.to_s} with raw args #{args}"
61
+
52
62
  arguments = args.cdr.nil? ? [] : args.cdr.to_a.map {|a| process_arg(a, env)}
53
63
  result = nil
54
64
 
@@ -56,11 +66,11 @@ module Lisp
56
66
  result = if arguments[-1].instance_of?(Proc)
57
67
  target.value.send(@value, *(arguments[0..-2]), &arguments[-1])
58
68
  else
59
- # puts "Sending #{@value} with #{arguments}"
69
+ # puts "Sending #{@value} to #{target} with processed args #{arguments}"
60
70
  target.value.send(@value, *arguments)
61
71
  end
62
72
  rescue Exception => e
63
- return Lisp::Debug.process_error("Exception sending #{@value}: #{e}", env)
73
+ return Lisp::Debug.process_error("Exception sending #{@value} - #{e.name}", env)
64
74
  end
65
75
 
66
76
  convert_value(result)
@@ -2,172 +2,13 @@ module Lisp
2
2
 
3
3
  class Frame < Atom
4
4
 
5
- def self.register
6
- 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|
7
- Lisp::Frame::make_frame_impl(args, env)
8
- end
9
-
10
- Primitive.register("has-slot?", "(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|
11
- Lisp::Frame::has_slot_impl(args, env)
12
- end
13
-
14
- Primitive.register("get-slot", "(get-slot _frame_ _slot-name_)\n\nThe get-slot function is used to retrieve values from frame slots") do |args, env|
15
- Lisp::Frame::get_slot_impl(args, env)
16
- end
17
-
18
- Primitive.register("get-slot-if", "(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|
19
- Lisp::Frame::get_slot_if_impl(args, env)
20
- end
21
-
22
- Primitive.register("remove-slot!", "(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|
23
- Lisp::Frame::remove_slot_impl(args, env)
24
- end
25
-
26
- Primitive.register("set-slot!", "(set-slot! frame slot-name new-value)\n\nThe set-slot! function is used to change values in frame slots") do |args, env|
27
- Lisp::Frame::set_slot_impl(args, env)
28
- end
29
-
30
- 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|
31
- Lisp::Frame::send_impl(args, env)
32
- end
33
-
34
- 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|
35
- Lisp::Frame::send_super_impl(args, env)
36
- end
37
-
38
- Primitive.register("clone", "(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|
39
- Lisp::Frame::clone_impl(args, env)
40
- end
41
-
42
- Primitive.register("keys", "(keys frame)\n\nReturn a list of the keys in the frame.") do |args, env|
43
- Lisp::Frame::keys_impl(args, env)
44
- end
45
-
46
- end
47
-
48
-
49
- def self.make_frame_impl(args, env)
50
- c = args
51
- m = {}
52
- while !c.nil?
53
- k = c.car
54
- return Lisp::Debug.process_error("Slot names must be a symbol, found a {k.type}.", env) unless k.symbol?
55
- return Lisp::Debug.process_error("Slot names must end in a colon, found '#{k}'.", env) unless k.naked?
56
- v = c.cadr.evaluate(env)
57
- m[k] = v
58
- c = c.cddr
59
- end
60
-
61
- Lisp::Frame.with_map(m)
62
- end
63
-
64
-
65
- def self.has_slot_impl(args, env)
66
- frame = args.car.evaluate(env)
67
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
68
- key = args.cadr.evaluate(env)
69
- return Lisp::Debug.process_error("Frame key must be a symbol but was #{key.type}.", env) unless key.symbol?
70
- return Lisp::TRUE if frame.has_slot?(key)
71
- Lisp::FALSE
72
- end
73
-
74
-
75
- def self.get_slot_impl(args, env)
76
- frame = args.car.evaluate(env)
77
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
78
- key = args.cadr.evaluate(env)
79
- return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol?
80
- return Lisp::Debug.process_error("Frame key (#{key.to_s}) must name an existing slot.", env) unless frame.has_slot?(key)
81
- frame.get(key)
82
- end
83
-
84
-
85
- def self.get_slot_if_impl(args, env)
86
- frame = args.car.evaluate(env)
87
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
88
- key = args.cadr.evaluate(env)
89
- return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol?
90
- frame.get(key)
91
- end
92
-
93
-
94
- def self.remove_slot_impl(args, env)
95
- frame = args.car.evaluate(env)
96
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
97
- key = args.cadr.evaluate(env)
98
- return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol?
99
- return Lisp::TRUE if frame.remove(key)
100
- Lisp::FALSE
101
- end
102
-
103
-
104
- def self.set_slot_impl(args, env)
105
- frame = args.car.evaluate(env)
106
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
107
- key = args.cadr.evaluate(env)
108
- return Lisp::Debug.process_error("Frame key (#{key.to_s}) must be a symbol but was #{key.type}.", env) unless key.symbol?
109
- value = args.caddr.evaluate(env)
110
- frame.at_put(key, value)
111
- end
112
-
113
-
114
- def self.send_impl(args, env)
115
- frame = args.car.evaluate(env)
116
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
117
- selector = args.cadr.evaluate(env)
118
- return Lisp::Debug.process_error("Selector must be a symbol but was #{selector.type}.", env) unless selector.symbol?
119
- return Lisp::Debug.process_error("Message sent must name an existing slot in the receiver.", env) unless frame.has_slot?(selector)
120
- func = frame.get(selector)
121
- return Lisp::Debug.process_error("Message sent must select a function slot but was #{func.type}.", env) unless func.function?
122
- params = args.cddr
123
- frame_env = Lisp::EnvironmentFrame.extending(env, frame)
124
- frame_env.bind_locally(Symbol.named("self"), frame)
125
- func.apply_to(params, frame_env)
126
- end
127
-
128
- def self.get_super_function(selector, env)
129
- f = env.frame
130
- return nil if f.nil?
131
- f.parents.each do |p|
132
- func = p.get(selector)
133
- return func unless func.nil?
134
- end
135
- nil
136
- end
137
-
138
- def self.send_super_impl(args, env)
139
- return Lisp::Debug.process_error("super can only be used within the context of a frame.", env) unless env.frame
140
- selector = args.car.evaluate(env)
141
- return Lisp::Debug.process_error("Selector must be a symbol but was #{selector.type}.", env) unless selector.symbol?
142
- func = get_super_function(selector, env)
143
- return Lisp::Debug.process_error("Message sent must select a function slot but was #{func.type}.", env) unless func && func.function?
144
- params = args.cdr
145
- frame_env = Lisp::EnvironmentFrame.extending(env, env.frame)
146
- frame_env.bind_locally(Symbol.named("self"), env.frame)
147
- func.apply_to(params, frame_env)
148
- end
149
-
150
-
151
- def self.clone_impl(args, env)
152
- frame = args.car.evaluate(env)
153
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
154
- frame.clone
155
- end
156
-
157
-
158
- def self.keys_impl(args, env)
159
- frame = args.car.evaluate(env)
160
- return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
161
- ConsCell.array_to_list(frame.value.keys)
162
- end
163
-
164
-
165
5
  def self.with_map(m)
166
6
  self.new(m)
167
7
  end
168
8
 
169
- def initialize(m=nil)
170
- @value = m || {}
9
+ def initialize(m = {})
10
+ @value = m
11
+ self
171
12
  end
172
13
 
173
14
 
@@ -285,11 +126,11 @@ module Lisp
285
126
  nil
286
127
  end
287
128
 
288
- def eq?(other)
129
+ def equal?(other)
289
130
  return false unless other.frame?
290
131
  return false unless @value.length == other.value.length
291
132
  @value.each do |k, v|
292
- return false unless Lisp::Equivalence.equal_check(other.value[k], v).value
133
+ return false unless other.value[k].equal?(v)
293
134
  end
294
135
  true
295
136
  end
@@ -2,7 +2,7 @@ module Lisp
2
2
 
3
3
  class Function < Atom
4
4
 
5
- attr_reader :doc, :arity, :name
5
+ attr_reader :doc, :arity, :name, :env, :body
6
6
 
7
7
  def compute_required_argument_count(args)
8
8
  a = args
@@ -37,10 +37,11 @@ module Lisp
37
37
  if @var_args
38
38
  return Lisp::Debug.process_error("#{@name} expected at least #{@arity} parameters, received #{parameters.length}.", env) if parameters.length < @arity
39
39
  else
40
+ puts "#{@name} #{@arguments.print_string} #{@body.print_string}" unless parameters.length == @arity
41
+ puts caller unless parameters.length == @arity
40
42
  return Lisp::Debug.process_error("#{@name} expected #{@arity} parameters, received #{parameters.length}.", env) unless parameters.length == @arity
41
43
  end
42
-
43
- local_env = EnvironmentFrame.extending(@env, env.frame)
44
+ local_env = EnvironmentFrame.extending(@env, @name, env.frame)
44
45
  local_env.previous = env
45
46
  self_sym = Symbol.named("self")
46
47
  if env.frame
@@ -2,7 +2,7 @@ module Lisp
2
2
 
3
3
  class Macro < Atom
4
4
 
5
- attr_reader :doc
5
+ attr_reader :name, :doc, :body
6
6
 
7
7
  def compute_required_argument_count(args)
8
8
  a = args
@@ -20,6 +20,7 @@ module Lisp
20
20
  end
21
21
 
22
22
  def initialize(name, arguments, doc, body, env)
23
+ #puts "Macro#initialize #{name} #{arguments.to_a}"
23
24
  sig = ([name] << arguments.to_a).flatten
24
25
  @doc = "(#{(sig.collect {|e| e.to_s}).join(" ")})"
25
26
  @name = name
@@ -33,14 +34,12 @@ module Lisp
33
34
 
34
35
  def expand(parameters, env, should_eval)
35
36
  if @var_args
36
- return Lisp::Debug.process_error("#{@name} expected at least
37
- ##{@required_argument_count} parameters, received #{parameters.length}.", env) if parameters.length < @required_argument_count
37
+ return Lisp::Debug.process_error("#{@name} expected at least #{@required_argument_count} parameters, received #{parameters.length}.", env) if parameters.length < @required_argument_count
38
38
  else
39
- return Lisp::Debug.process_error("#{@name} expected
40
- ##{@required_argument_count} parameters, received #{parameters.length}.", env) unless parameters.length == @required_argument_count
39
+ return Lisp::Debug.process_error("#{@name} expected #{@required_argument_count} parameters, received #{parameters.length}.", env) unless parameters.length == @required_argument_count
41
40
  end
42
41
 
43
- local_env = EnvironmentFrame.extending(@env, env.frame)
42
+ local_env = EnvironmentFrame.extending(@env, @name, env.frame)
44
43
  self_sym = Symbol.named("self")
45
44
  if env.frame
46
45
  local_env.bind_locally(self_sym, env.frame)
@@ -63,8 +62,14 @@ module Lisp
63
62
  accumulating_arg = arg if arg.symbol?
64
63
  end
65
64
  local_env.bind_locally(accumulating_arg, Lisp::ConsCell.array_to_list(accumulated_params)) if accumulating_arg
65
+
66
+ #puts "expanding #{@name}"
67
+ #puts " #{@body.print_string}"
66
68
 
67
- @body.evaluate(local_env)
69
+ result = @body.evaluate(local_env)
70
+
71
+ #puts " #{result.print_string}"
72
+ result
68
73
  end
69
74
 
70
75
  def internal_apply_to(parameters, env, should_eval)
@@ -91,7 +96,7 @@ module Lisp
91
96
  def type
92
97
  :macro
93
98
  end
94
-
99
+
95
100
  end
96
101
 
97
102
  end