rubymotionlisp 0.2.2 → 1.0.0

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +129 -2
  3. data/lib/rubylisp/atom.rb +25 -6
  4. data/lib/rubylisp/boolean.rb +9 -6
  5. data/lib/rubylisp/builtins.rb +33 -0
  6. data/lib/rubylisp/character.rb +14 -275
  7. data/lib/rubylisp/class_object.rb +56 -0
  8. data/lib/rubylisp/cons_cell.rb +50 -20
  9. data/lib/rubylisp/environment.rb +27 -0
  10. data/lib/rubylisp/environment_frame.rb +24 -6
  11. data/lib/rubylisp/eof_object.rb +26 -0
  12. data/lib/rubylisp/exception.rb +61 -61
  13. data/lib/rubylisp/ext.rb +32 -6
  14. data/lib/rubylisp/ffi_new.rb +2 -1
  15. data/lib/rubylisp/ffi_send.rb +15 -5
  16. data/lib/rubylisp/frame.rb +5 -164
  17. data/lib/rubylisp/function.rb +4 -3
  18. data/lib/rubylisp/macro.rb +13 -8
  19. data/lib/rubylisp/{object.rb → native_object.rb} +0 -15
  20. data/lib/rubylisp/number.rb +5 -0
  21. data/lib/rubylisp/parser.rb +81 -52
  22. data/lib/rubylisp/port.rb +27 -0
  23. data/lib/rubylisp/prim_alist.rb +115 -0
  24. data/lib/rubylisp/prim_assignment.rb +61 -0
  25. data/lib/rubylisp/prim_character.rb +273 -0
  26. data/lib/rubylisp/{ffi_class.rb → prim_class_object.rb} +16 -69
  27. data/lib/rubylisp/prim_environment.rb +203 -0
  28. data/lib/rubylisp/prim_equivalence.rb +93 -0
  29. data/lib/rubylisp/prim_frame.rb +166 -0
  30. data/lib/rubylisp/prim_io.rb +266 -0
  31. data/lib/rubylisp/prim_list_support.rb +496 -0
  32. data/lib/rubylisp/{logical.rb → prim_logical.rb} +9 -14
  33. data/lib/rubylisp/prim_math.rb +397 -0
  34. data/lib/rubylisp/prim_native_object.rb +21 -0
  35. data/lib/rubylisp/prim_relational.rb +42 -0
  36. data/lib/rubylisp/{special_forms.rb → prim_special_forms.rb} +97 -84
  37. data/lib/rubylisp/prim_string.rb +792 -0
  38. data/lib/rubylisp/prim_system.rb +55 -0
  39. data/lib/rubylisp/prim_type_checks.rb +58 -0
  40. data/lib/rubylisp/prim_vector.rb +497 -0
  41. data/lib/rubylisp/primitive.rb +51 -6
  42. data/lib/rubylisp/string.rb +4 -803
  43. data/lib/rubylisp/symbol.rb +0 -1
  44. data/lib/rubylisp/tokenizer.rb +160 -136
  45. data/lib/rubylisp/vector.rb +10 -31
  46. data/lib/rubymotion/debug.rb +40 -0
  47. data/lib/rubymotion/require-fix.rb +1 -0
  48. data/lib/rubymotionlisp.rb +4 -0
  49. metadata +28 -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/motion_builtins.rb +0 -31
  57. data/lib/rubylisp/relational.rb +0 -46
  58. data/lib/rubylisp/system.rb +0 -20
  59. data/lib/rubylisp/testing.rb +0 -136
  60. data/lib/rubylisp/type_checks.rb +0 -60
@@ -0,0 +1,93 @@
1
+ module Lisp
2
+
3
+ class PrimEquivalence
4
+
5
+ def self.register
6
+ Primitive.register("=", "2", "(= n1 n2)\n\nEquivalent to (eqv? n1 n2)") do |args, env|
7
+ Lisp::PrimEquivalence::eqv_impl(args, env)
8
+ end
9
+
10
+ Primitive.register("==", "2", "(== n1 n2)\n\nEquivalent to (eqv? n1 n2)") do |args, env|
11
+ Lisp::PrimEquivalence::eqv_impl(args, env)
12
+ end
13
+
14
+ Primitive.register("!=", "2", "(!= n1 n2)\n\nEquivalent to (neqv? n1 n2).") do |args, env|
15
+ Lisp::PrimEquivalence::neqv_impl(args, env)
16
+ end
17
+
18
+ Primitive.register("/=", "2", "(/= n1 n2)\n\nEquivalent to (neqv? n1 n2).") do |args, env|
19
+ Lisp::PrimEquivalence::neqv_impl(args, env)
20
+ end
21
+
22
+ Primitive.register("eq?", "2") do |args, env|
23
+ Lisp::PrimEquivalence::eq_impl(args, env)
24
+ end
25
+
26
+ Primitive.register("neq?", "2") do |args, env|
27
+ Lisp::PrimEquivalence::neq_impl(args, env)
28
+ end
29
+
30
+ Primitive.register("eqv?", "2") do |args, env|
31
+ Lisp::PrimEquivalence::eqv_impl(args, env)
32
+ end
33
+
34
+ Primitive.register("neqv?", "2") do |args, env|
35
+ Lisp::PrimEquivalence::eqv_impl(args, env)
36
+ end
37
+
38
+ Primitive.register("equal?", "2") do |args, env|
39
+ Lisp::PrimEquivalence::equal_impl(args, env)
40
+ end
41
+
42
+ Primitive.register("nequal?", "2") do |args, env|
43
+ Lisp::PrimEquivalence::nequal_impl(args, env)
44
+ end
45
+
46
+ end
47
+
48
+
49
+ def self.eqv_impl(args, env)
50
+ o1 = args.car
51
+ o2 = args.cadr
52
+ Lisp::Boolean.with_value(o1.eqv?(o2))
53
+ end
54
+
55
+
56
+ def self.neqv_impl(args, env)
57
+ o1 = args.car
58
+ o2 = args.cadr
59
+ Lisp::Boolean.with_value(!o1.eqv?(o2))
60
+ end
61
+
62
+
63
+ def self.eq_impl(args, env)
64
+ o1 = args.car
65
+ o2 = args.cadr
66
+ Lisp::Boolean.with_value(o1.eq?(o2))
67
+ end
68
+
69
+
70
+ def self.neq_impl(args, env)
71
+ o1 = args.car
72
+ o2 = args.cadr
73
+ Lisp::Boolean.with_value(!o1.eq?(o2))
74
+ end
75
+
76
+
77
+ def self.equal_impl(args, env)
78
+ o1 = args.car
79
+ o2 = args.cadr
80
+ Lisp::Boolean.with_value(o1.equal?(o2))
81
+ end
82
+
83
+
84
+ def self.nequal_impl(args, env)
85
+ o1 = args.car
86
+ o2 = args.cadr
87
+ Lisp::Boolean.with_value(!o1.equal?(o2))
88
+ end
89
+
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,166 @@
1
+ module Lisp
2
+
3
+ class PrimFrame
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::PrimFrame::make_frame_impl(args, env)
8
+ end
9
+
10
+ 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|
11
+ Lisp::PrimFrame::has_slot_impl(args, env)
12
+ end
13
+
14
+ 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|
15
+ Lisp::PrimFrame::get_slot_impl(args, env)
16
+ end
17
+
18
+ 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|
19
+ Lisp::PrimFrame::get_slot_if_impl(args, env)
20
+ end
21
+
22
+ 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|
23
+ Lisp::PrimFrame::remove_slot_impl(args, env)
24
+ end
25
+
26
+ 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|
27
+ Lisp::PrimFrame::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::PrimFrame::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::PrimFrame::send_super_impl(args, env)
36
+ end
37
+
38
+ 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|
39
+ Lisp::PrimFrame::clone_impl(args, env)
40
+ end
41
+
42
+ Primitive.register("keys", "1", "(keys frame)\n\nReturn a list of the keys in the frame.") do |args, env|
43
+ Lisp::PrimFrame::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
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
67
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
68
+ key = args.cadr
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
77
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
78
+ key = args.cadr
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
87
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
88
+ key = args.cadr
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
96
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
97
+ key = args.cadr
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
106
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
107
+ key = args.cadr
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
110
+ frame.at_put(key, value)
111
+ end
112
+
113
+
114
+ def self.send_impl(args, env)
115
+ frame = args.car
116
+ return Lisp::Debug.process_error("Frame data must be a frame but was #{frame.type}.", env) unless frame.frame?
117
+ selector = args.cadr
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, selector.to_s, 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
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, selector.to_s, 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
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
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
+ end
165
+
166
+ end
@@ -0,0 +1,266 @@
1
+ module Lisp
2
+
3
+ class PrimIo
4
+
5
+ def self.register
6
+ Primitive.register("load", "1") {|args, env| Lisp::PrimIo::load_impl(args, env) }
7
+ Primitive.register("open-input-file", "1") {|args, env| Lisp::PrimIo::open_input_file_impl(args, env) }
8
+ Primitive.register("open-output-file", "1|2") {|args, env| Lisp::PrimIo::open_output_file_impl(args, env) }
9
+ Primitive.register("close-port", "1") {|args, env| Lisp::PrimIo::close_port_impl(args, env) }
10
+ Primitive.register("write-string", "1|2") {|args, env| Lisp::PrimIo::write_string_impl(args, env) }
11
+ Primitive.register("newline", "0|1") {|args, env| Lisp::PrimIo::newline_impl(args, env) }
12
+ Primitive.register("write", "1|2") {|args, env| Lisp::PrimIo::write_impl(args, env) }
13
+ Primitive.register("read", "0|1") {|args, env| Lisp::PrimIo::read_impl(args, env) }
14
+ Primitive.register("list-directory", "1|2") {|args, env| Lisp::PrimIo::list_directory_impl(args, env) }
15
+ Primitive.register("eof-object?", "1") {|args, env| Lisp::PrimIo::eof_objectp_impl(args, env) }
16
+ Primitive.register("format", ">=2") {|args, env| Lisp::PrimIo::format_impl(args, env) }
17
+ # Primitive.register("load-library", "1") {|args, env| Lisp::PrimIo::load_library_impl(args, env) }
18
+ # Primitive.register("load-project", "1") {|args, env| Lisp::PrimIo::load_project_impl(args, env) }
19
+ Primitive.register("trace", "*") {|args, env| puts "Trace: #{(args.to_a.map {|a| a.value.to_s}).join(' ')}"; nil}
20
+ Primitive.register("error", "*") {|args, env| App.alert((args.to_a.map {|a| a.value.to_s}).join(' '))}
21
+ Primitive.register("alert", "*") {|args, env| App.alert((args.to_a.map {|a| a.value.to_s}).join(' '))}
22
+ end
23
+
24
+
25
+ def self.load_impl(args, env)
26
+ fname = args.car
27
+ return Lisp::Debug.process_error("'load' requires a string argument.", env) unless fname.string?
28
+ filename = fname.value.end_with?(".lsp") ? fname.value : "#{fname.value}.lsp"
29
+ Lisp::Parser.new.process_file(filename)
30
+ Lisp::String.with_value("OK")
31
+ end
32
+
33
+
34
+ def self.open_input_file_impl(args, env)
35
+ fname = args.car
36
+ return Lisp::Debug.process_error("'open-input-file' requires a string argument.", env) unless fname.string?
37
+ f = File.open(fname.value, "r")
38
+ f ? Lisp::Port.with_value(f) : nil
39
+ end
40
+
41
+
42
+ def self.open_output_file_impl(args, env)
43
+ fname = args.car
44
+ return Lisp::Debug.process_error("'load' requires a string argument.", env) unless fname.string?
45
+ mode = (args.length == 2 && args.cadr.true?) ? "a" : "w"
46
+ f = File.open(fname.value, mode)
47
+ f ? Lisp::Port.with_value(f) : nil
48
+ end
49
+
50
+
51
+ def self.close_port_impl(args, env)
52
+ p = args.car
53
+ return Lisp::Debug.process_error("'close-port' requires a port argument.", env) unless p.port?
54
+ p.value.close
55
+ Lisp::String.with_value("OK")
56
+ end
57
+
58
+
59
+ def self.write_string_impl(args, env)
60
+ s = args.car
61
+ return Lisp::Debug.process_error("'write-string' requires a string first argument.", env) unless s.string?
62
+
63
+ if args.length == 2
64
+ p = args.cadr
65
+ return Lisp::Debug.process_error("'write-string' requires a port as it's second argument.", env) unless p.port?
66
+ port = p.value
67
+ else
68
+ port = $stdout
69
+ end
70
+
71
+ port.write(s.value)
72
+ end
73
+
74
+
75
+ def self.newline_impl(args, env)
76
+ if args.length == 1
77
+ p = args.car
78
+ return Lisp::Debug.process_error("'newline' requires a port as it's argument.", env) unless p.port?
79
+ port = p.value
80
+ else
81
+ port = $stdout
82
+ end
83
+
84
+ port.write("\n")
85
+ end
86
+
87
+
88
+ def self.write_impl(args, env)
89
+ if args.length == 2
90
+ p = args.cadr
91
+ return Lisp::Debug.process_error("'write' requires a port as it's second argument.", env) unless p.port?
92
+ port = p.value
93
+ else
94
+ port = $stdout
95
+ end
96
+
97
+ port.write(args.car.print_string)
98
+ end
99
+
100
+
101
+ def self.read_impl(args, env)
102
+ if args.length == 1
103
+ p = args.car
104
+ return Lisp::Debug.process_error("'read' requires a port as it's argument.", env) unless p.port?
105
+ port = p.value
106
+ else
107
+ port = $stdin
108
+ end
109
+
110
+ Lisp::Parser.new.parse_object_from_file(port)
111
+ end
112
+
113
+
114
+ def self.list_directory_impl(args, env)
115
+ return Lisp::Debug.process_error("'list-directory' requires a string as it's first argument.", env) unless args.car.string?
116
+ dir = args.car.value
117
+ fpart = (args.length == 2) ? args.cadr.value : "*"
118
+ filenames = Dir.glob(File.join(dir, fpart))
119
+ Lisp::ConsCell.array_to_list(filenames.map {|f| Lisp::String.with_value(f)})
120
+ end
121
+
122
+
123
+ def self.eof_objectp_impl(args, env)
124
+ Boolean.with_value(args.car.eof_object?)
125
+ end
126
+
127
+
128
+ def self.format_impl(args, env)
129
+ destination = args.car
130
+ return Lisp::Debug.process_error("'format' requires a port or boolean as it's first argument.", env) unless destination.port? || destination.boolean?
131
+
132
+ control_string_obj = args.cadr
133
+ return Lisp::Debug.process_error("'format' requires a string as it's second argument.", env) unless control_string_obj.string?
134
+ control_string = control_string_obj.value
135
+
136
+ arguments = args.cddr
137
+
138
+ number_of_substitutions = control_string.count('~')
139
+ parts = []
140
+ start = 0
141
+ i = 0
142
+ numeric_arg = 0
143
+ at_modifier = false
144
+
145
+ while i < control_string.length
146
+ numeric_arg = 0
147
+ at_modifier = false
148
+
149
+ if control_string[i] == '~'
150
+ parts << control_string[start...i]
151
+ i += 1
152
+ start = i
153
+ i += 1 while '0123456789'.include?(control_string[i])
154
+ if i == start
155
+ if control_string[i] == '#'
156
+ numeric_arg = arguments.length
157
+ i += 1
158
+ elsif 'vV'.include?(control_string[i])
159
+ if arguments.car.number?
160
+ numeric_arg = arguments.car.value
161
+ arguments = arguments.cdr
162
+ else
163
+ return Lisp::Debug.process_error("'format' encountered a size argument mismatch at index #{i}.", env)
164
+ end
165
+ i += 1
166
+ else
167
+ numeric_arg = 0
168
+ end
169
+ else
170
+ numeric_arg = control_string[start...i].to_i
171
+ end
172
+ if control_string[i] == '@'
173
+ at_modifier = true
174
+ i += 1
175
+ end
176
+
177
+ case control_string[i]
178
+ when 'A', 'a', 'S', 's'
179
+ substitution = ('Aa'.include?(control_string[i])) ? arguments.car.print_string : arguments.car.to_s
180
+ padding = substitution.length < numeric_arg ? (" " * (numeric_arg - substitution.length)) : ""
181
+ parts << padding if at_modifier
182
+ parts << substitution
183
+ parts << padding unless at_modifier
184
+ arguments = arguments.cdr
185
+ start = i + 1
186
+ when '%'
187
+ parts << ((numeric_arg > 0) ? ("\n" * numeric_arg) : "\n")
188
+ start = i + 1
189
+ when '~'
190
+ parts << ((numeric_arg > 0) ? ("~" * numeric_arg) : "~")
191
+ start = i + 1
192
+ when "\n"
193
+ while control_string[i] =~ /[[:space:]]/
194
+ i += 1
195
+ end
196
+ parts << "\n" if at_modifier
197
+ start = i
198
+ i -= 1
199
+ else
200
+ return Lisp::Debug.process_error("'format' encountered an unsupported substitution at index #{i}.", env)
201
+ end
202
+ end
203
+ i += 1
204
+ end
205
+ parts << control_string[start..i] if start < control_string.length
206
+ return Lisp::Debug.process_error("'format' found a mismatch in the number of substitutions and arguments.", env) if i < control_string.length || !arguments.nil?
207
+
208
+ combined_string = parts.join
209
+
210
+ if destination.port?
211
+ destination.value.write(combined_string)
212
+ elsif destination.value
213
+ $stdout.write(combined_string)
214
+ else
215
+ return Lisp::String.with_value(combined_string)
216
+ end
217
+
218
+ end
219
+
220
+
221
+ # def self.load_library_impl(args, env)
222
+ # library_name = args.car
223
+ # return Lisp::Debug.process_error("'load-library' requires a string or symbol argument.", env) unless library_name.string? || library_name.symbol?
224
+ # Dir.chdir(File.join(App.documents_path, "libraries", "#{library_name}.lib")) do |d|
225
+ # if File.exists?("load.lsp")
226
+ # File.open("load.lsp") do |f|
227
+ # contents = f.read()
228
+ # Lisp::Parser.new.parse_and_eval_all(contents)
229
+ # end
230
+ # else
231
+ # Dir.glob("*.lsp") do |filename|
232
+ # File.open(filename) do |f|
233
+ # contents = f.read()
234
+ # Lisp::Parser.new.parse_and_eval_all(contents)
235
+ # end
236
+ # end
237
+ # end
238
+ # end
239
+ # Lisp::String.with_value("OK")
240
+ # end
241
+
242
+
243
+ # def self.load_project_impl(args, env)
244
+ # project_name = args.car
245
+ # return Lisp::Debug.process_error("'load-project' requires a string or symbol argument.", env) unless project_name.string? || project_name.symbol?
246
+ # Dir.chdir(File.join(App.documents_path, "projects", "#{project_name}.prj")) do |d|
247
+ # if File.exists?("load.lsp")
248
+ # File.open("load.lsp") do |f|
249
+ # contents = f.read()
250
+ # Lisp::Parser.new.parse_and_eval_all(contents)
251
+ # end
252
+ # else
253
+ # Dir.glob("*.lsp") do |filename|
254
+ # File.open(filename) do |f|
255
+ # contents = f.read()
256
+ # Lisp::Parser.new.parse_and_eval_all(contents)
257
+ # end
258
+ # end
259
+ # end
260
+ # end
261
+ # Lisp::String.with_value("OK")
262
+ # end
263
+
264
+ end
265
+
266
+ end