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
@@ -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