rubylisp 0.2.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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