rubylisp 0.1.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.
- checksums.yaml +7 -0
- data/bin/rubylisp +14 -0
- data/lib/rubylisp/alist.rb +230 -0
- data/lib/rubylisp/assignment.rb +65 -0
- data/lib/rubylisp/atom.rb +149 -0
- data/lib/rubylisp/binding.rb +17 -0
- data/lib/rubylisp/boolean.rb +49 -0
- data/lib/rubylisp/builtins.rb +31 -0
- data/lib/rubylisp/character.rb +383 -0
- data/lib/rubylisp/cons_cell.rb +255 -0
- data/lib/rubylisp/environment_frame.rb +116 -0
- data/lib/rubylisp/equivalence.rb +118 -0
- data/lib/rubylisp/exception.rb +98 -0
- data/lib/rubylisp/ext.rb +122 -0
- data/lib/rubylisp/ffi_class.rb +162 -0
- data/lib/rubylisp/ffi_new.rb +32 -0
- data/lib/rubylisp/ffi_send.rb +83 -0
- data/lib/rubylisp/ffi_static.rb +22 -0
- data/lib/rubylisp/frame.rb +284 -0
- data/lib/rubylisp/function.rb +92 -0
- data/lib/rubylisp/io.rb +74 -0
- data/lib/rubylisp/list_support.rb +527 -0
- data/lib/rubylisp/logical.rb +38 -0
- data/lib/rubylisp/macro.rb +95 -0
- data/lib/rubylisp/math.rb +403 -0
- data/lib/rubylisp/number.rb +63 -0
- data/lib/rubylisp/object.rb +62 -0
- data/lib/rubylisp/parser.rb +184 -0
- data/lib/rubylisp/primitive.rb +45 -0
- data/lib/rubylisp/relational.rb +46 -0
- data/lib/rubylisp/special_forms.rb +454 -0
- data/lib/rubylisp/string.rb +841 -0
- data/lib/rubylisp/symbol.rb +56 -0
- data/lib/rubylisp/system.rb +19 -0
- data/lib/rubylisp/testing.rb +136 -0
- data/lib/rubylisp/tokenizer.rb +292 -0
- data/lib/rubylisp/type_checks.rb +58 -0
- data/lib/rubylisp/vector.rb +114 -0
- data/lib/rubylisp.rb +1 -0
- metadata +82 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
module Lisp
|
2
|
+
|
3
|
+
class FfiSend < Atom
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@value = name.to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply_to(args, env)
|
10
|
+
apply_to_without_evaluating(Lisp::ConsCell.array_to_list(args.to_a.map {|a| a.evaluate(env)}), env)
|
11
|
+
end
|
12
|
+
|
13
|
+
def convert_value(value)
|
14
|
+
case value.class.name
|
15
|
+
when "Fixnum", "Float"
|
16
|
+
Lisp::Number.with_value(value)
|
17
|
+
when "TrueClass"
|
18
|
+
Lisp::Boolean.TRUE
|
19
|
+
when "FalseClass"
|
20
|
+
Lisp::Boolean.FALSE
|
21
|
+
when "String"
|
22
|
+
Lisp::String.with_value(value)
|
23
|
+
when "Symbol"
|
24
|
+
Lisp::Symbol.named(value)
|
25
|
+
when "Array"
|
26
|
+
Lisp::ConsCell.array_to_list(value.map {|a| convert_value(a)})
|
27
|
+
else
|
28
|
+
Lisp::NativeObject.with_value(value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def process_arg(a, env)
|
34
|
+
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)
|
38
|
+
end
|
39
|
+
elsif a.list?
|
40
|
+
a.to_a.map {|i| process_arg(i, env)}
|
41
|
+
else
|
42
|
+
a.value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def apply_to_without_evaluating(args, env)
|
48
|
+
target = args.car
|
49
|
+
raise "Send target of '#{@value}' evaluated to nil." if target.nil?
|
50
|
+
raise "Target of an FFI send of '#{@value}' must be a wrapped ObjC object, was #{target}" unless target.object?
|
51
|
+
|
52
|
+
arguments = args.cdr.nil? ? [] : args.cdr.to_a.map {|a| process_arg(a, env)}
|
53
|
+
result = nil
|
54
|
+
|
55
|
+
begin
|
56
|
+
result = if arguments[-1].instance_of?(Proc)
|
57
|
+
target.value.send(@value, *(arguments[0..-2]), &arguments[-1])
|
58
|
+
else
|
59
|
+
# puts "Sending #{@value} with #{arguments}"
|
60
|
+
target.value.send(@value, *arguments)
|
61
|
+
end
|
62
|
+
rescue Exception => e
|
63
|
+
raise "Exception sending #{@value}: #{e}"
|
64
|
+
end
|
65
|
+
|
66
|
+
convert_value(result)
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
".#{@value}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def primitive?
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def type
|
78
|
+
:primitive
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Lisp
|
2
|
+
|
3
|
+
class FfiStatic < FfiSend
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@class_name, @value = name.split('/')
|
7
|
+
@klass = NativeObject.with_value(Object.const_get(@class_name))
|
8
|
+
end
|
9
|
+
|
10
|
+
def apply_to(args, env)
|
11
|
+
a = [@klass] + args.to_a
|
12
|
+
super(a, env)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@class_name}/#{@value}"
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
module Lisp
|
2
|
+
|
3
|
+
class Frame < Atom
|
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
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def self.make_frame_impl(args, env)
|
46
|
+
c = args
|
47
|
+
m = {}
|
48
|
+
while !c.nil?
|
49
|
+
k = c.car
|
50
|
+
raise "Slot names must be a symbol, found a {k.type}." unless k.symbol?
|
51
|
+
raise "Slot names must end in a colon, found '#{k}'." unless k.naked?
|
52
|
+
v = c.cadr.evaluate(env)
|
53
|
+
m[k] = v
|
54
|
+
c = c.cddr
|
55
|
+
end
|
56
|
+
|
57
|
+
Lisp::Frame.with_map(m)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def self.has_slot_impl(args, env)
|
62
|
+
frame = args.car.evaluate(env)
|
63
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
64
|
+
key = args.cadr.evaluate(env)
|
65
|
+
raise "Frame key must be a symbol but was #{key.type}." unless key.symbol?
|
66
|
+
return Lisp::TRUE if frame.has_slot?(key)
|
67
|
+
Lisp::FALSE
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def self.get_slot_impl(args, env)
|
72
|
+
frame = args.car.evaluate(env)
|
73
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
74
|
+
key = args.cadr.evaluate(env)
|
75
|
+
raise "Frame key (#{key.to_s}) must be a symbol but was #{key.type}." unless key.symbol?
|
76
|
+
raise "Frame key (#{key.to_s}) must name an existing slot." unless frame.has_slot?(key)
|
77
|
+
frame.get(key)
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def self.get_slot_if_impl(args, env)
|
82
|
+
frame = args.car.evaluate(env)
|
83
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
84
|
+
key = args.cadr.evaluate(env)
|
85
|
+
raise "Frame key (#{key.to_s}) must be a symbol but was #{key.type}." unless key.symbol?
|
86
|
+
frame.get(key)
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
def self.remove_slot_impl(args, env)
|
91
|
+
frame = args.car.evaluate(env)
|
92
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
93
|
+
key = args.cadr.evaluate(env)
|
94
|
+
raise "Frame key (#{key.to_s}) must be a symbol but was #{key.type}." unless key.symbol?
|
95
|
+
return Lisp::TRUE if frame.remove(key)
|
96
|
+
Lisp::FALSE
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
def self.set_slot_impl(args, env)
|
101
|
+
frame = args.car.evaluate(env)
|
102
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
103
|
+
key = args.cadr.evaluate(env)
|
104
|
+
raise "Frame key (#{key.to_s}) must be a symbol but was #{key.type}." unless key.symbol?
|
105
|
+
value = args.caddr.evaluate(env)
|
106
|
+
frame.at_put(key, value)
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def self.send_impl(args, env)
|
111
|
+
frame = args.car.evaluate(env)
|
112
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
113
|
+
selector = args.cadr.evaluate(env)
|
114
|
+
raise "Selector must be a symbol but was #{selector.type}." unless selector.symbol?
|
115
|
+
raise "Message sent must name an existing slot in the receiver." unless frame.has_slot?(selector)
|
116
|
+
func = frame.get(selector)
|
117
|
+
raise "Message sent must select a function slot but was #{func.type}." unless func.function?
|
118
|
+
params = args.cddr
|
119
|
+
frame_env = Lisp::EnvironmentFrame.extending(env, frame)
|
120
|
+
frame_env.bind_locally(Symbol.named("self"), frame)
|
121
|
+
func.apply_to(params, frame_env)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.get_super_function(selector, env)
|
125
|
+
f = env.frame
|
126
|
+
return nil if f.nil?
|
127
|
+
f.parents.each do |p|
|
128
|
+
func = p.get(selector)
|
129
|
+
return func unless func.nil?
|
130
|
+
end
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def self.send_super_impl(args, env)
|
135
|
+
raise "super can only be used within the context of a frame." unless env.frame
|
136
|
+
selector = args.car.evaluate(env)
|
137
|
+
raise "Selector must be a symbol but was #{selector.type}." unless selector.symbol?
|
138
|
+
func = get_super_function(selector, env)
|
139
|
+
raise "Message sent must select a function slot but was #{func.type}." unless func && func.function?
|
140
|
+
params = args.cdr
|
141
|
+
frame_env = Lisp::EnvironmentFrame.extending(env, env.frame)
|
142
|
+
frame_env.bind_locally(Symbol.named("self"), env.frame)
|
143
|
+
func.apply_to(params, frame_env)
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def self.clone_impl(args, env)
|
148
|
+
frame = args.car.evaluate(env)
|
149
|
+
raise "Frame data must be a frame but was #{frame.type}." unless frame.frame?
|
150
|
+
frame.clone
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def self.with_map(m)
|
155
|
+
self.new(m)
|
156
|
+
end
|
157
|
+
|
158
|
+
def initialize(m=nil)
|
159
|
+
@value = m || {}
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def clone
|
164
|
+
Lisp::Frame.with_map(@value.clone)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
def is_parent_key(k)
|
169
|
+
k.to_s[-2] == "*"
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
def local_slots
|
174
|
+
@value.keys
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def inherited_value_slots
|
179
|
+
parent_frames = parent_slots.collect {|pk| get(pk)}
|
180
|
+
parent_slots = parent_frames.collect {|p| p.inherited_value_slots}
|
181
|
+
local_value_slots = Set[local_slots.reject {|s| is_parent_key(k)}]
|
182
|
+
parent_slots.inject(local_value_slots) {|all, s| all + s}
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
def has_parent_slots?
|
187
|
+
@value.keys.any? {|k| is_parent_key(k)}
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
def parent_slots
|
192
|
+
@value.keys.select {|k| is_parent_key(k)}
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
def parents
|
197
|
+
parent_slots.collect {|pk| @value[pk]}
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
def has_slot_locally?(n)
|
202
|
+
@value.has_key?(n)
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def has_slot?(n)
|
207
|
+
return true if has_slot_locally?(n)
|
208
|
+
return false unless has_parent_slots?
|
209
|
+
return parents.any? {|p| p.has_slot?(n)}
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
def get(key)
|
214
|
+
return @value[key] if has_slot_locally?(key)
|
215
|
+
parents.each do |p|
|
216
|
+
value = p.get(key)
|
217
|
+
return value unless value.nil?
|
218
|
+
end
|
219
|
+
nil
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
def remove(key)
|
224
|
+
return false unless has_slot_locally?(key)
|
225
|
+
@value.delete(key)
|
226
|
+
true
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
def at_put(key, value)
|
231
|
+
return @value[key] = value if !has_slot?(key) || has_slot_locally?(key)
|
232
|
+
parents.each do |p|
|
233
|
+
v = p.at_put(key, value)
|
234
|
+
return v unless v.nil?
|
235
|
+
end
|
236
|
+
nil
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
def lisp_object?
|
241
|
+
true
|
242
|
+
end
|
243
|
+
|
244
|
+
def type
|
245
|
+
:frame
|
246
|
+
end
|
247
|
+
|
248
|
+
def empty?
|
249
|
+
@value.empty?
|
250
|
+
end
|
251
|
+
|
252
|
+
def frame?
|
253
|
+
true
|
254
|
+
end
|
255
|
+
|
256
|
+
def length
|
257
|
+
return @value.length
|
258
|
+
end
|
259
|
+
|
260
|
+
def car
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
|
264
|
+
def cdr
|
265
|
+
nil
|
266
|
+
end
|
267
|
+
|
268
|
+
def eq?(other)
|
269
|
+
return false unless other.frame?
|
270
|
+
return false unless @value.length == other.value.length
|
271
|
+
@value.each do |k, v|
|
272
|
+
return false unless Lisp::Equivalence.equal_check(other.value[k], v).value
|
273
|
+
end
|
274
|
+
true
|
275
|
+
end
|
276
|
+
|
277
|
+
def to_s
|
278
|
+
pairs = @value.collect {|k, v| "#{k.to_s} #{v.to_s}"}
|
279
|
+
"{#{pairs.join(' ')}}"
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Lisp
|
2
|
+
|
3
|
+
class Function < Atom
|
4
|
+
|
5
|
+
attr_reader :doc
|
6
|
+
|
7
|
+
def compute_required_argument_count(args)
|
8
|
+
a = args
|
9
|
+
@required_argument_count = 0
|
10
|
+
@var_args = false
|
11
|
+
while a
|
12
|
+
if a.symbol?
|
13
|
+
@var_args = true
|
14
|
+
return
|
15
|
+
else
|
16
|
+
@required_argument_count += 1
|
17
|
+
end
|
18
|
+
a = a.cdr
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def initialize(name, arguments, doc, body, env)
|
24
|
+
sig = ([name] << arguments.to_a).flatten
|
25
|
+
@doc = "(#{(sig.collect {|e| e.to_s}).join(" ")})"
|
26
|
+
@name = name
|
27
|
+
@arguments = arguments
|
28
|
+
@doc = [@doc, doc].join("\n\n") unless doc.nil? || doc.to_s.empty?
|
29
|
+
@body = body
|
30
|
+
@env = env
|
31
|
+
@local_env = nil
|
32
|
+
compute_required_argument_count(@arguments)
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def internal_apply_to(parameters, env, should_eval)
|
37
|
+
if @var_args
|
38
|
+
raise "#{@name} expected at least #{@required_argument_count} parameters, received #{parameters.length}." if parameters.length < @required_argument_count
|
39
|
+
else
|
40
|
+
raise "#{@name} expected #{@required_argument_count} parameters, received #{parameters.length}." unless parameters.length == @required_argument_count
|
41
|
+
end
|
42
|
+
|
43
|
+
local_env = EnvironmentFrame.extending(@env, env.frame)
|
44
|
+
self_sym = Symbol.named("self")
|
45
|
+
if env.frame
|
46
|
+
local_env.bind_locally(self_sym, env.frame)
|
47
|
+
elsif env.local_binding_for(self_sym)
|
48
|
+
local_env.bind_locally(self_sym, env.value_of(self_sym))
|
49
|
+
end
|
50
|
+
arg = @arguments
|
51
|
+
param = parameters
|
52
|
+
accumulating_arg = nil
|
53
|
+
accumulated_params = []
|
54
|
+
while !param.nil?
|
55
|
+
param_value = should_eval ? param.car.evaluate(env) : param.car
|
56
|
+
if accumulating_arg
|
57
|
+
accumulated_params << param_value
|
58
|
+
else
|
59
|
+
local_env.bind_locally(arg.car, param_value) unless arg.car.nil?
|
60
|
+
end
|
61
|
+
param = param.cdr
|
62
|
+
arg = arg.cdr unless accumulating_arg
|
63
|
+
accumulating_arg = arg if arg.symbol?
|
64
|
+
end
|
65
|
+
local_env.bind_locally(accumulating_arg, Lisp::ConsCell.array_to_list(accumulated_params)) if accumulating_arg
|
66
|
+
|
67
|
+
@body.evaluate_each(local_env)
|
68
|
+
end
|
69
|
+
|
70
|
+
def apply_to(parameters, env)
|
71
|
+
internal_apply_to(parameters, env, true)
|
72
|
+
end
|
73
|
+
|
74
|
+
def apply_to_without_evaluating(parameters, env)
|
75
|
+
internal_apply_to(parameters, env, false)
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
"<function: #{@name}>"
|
80
|
+
end
|
81
|
+
|
82
|
+
def function?
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
def type
|
87
|
+
:function
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/lib/rubylisp/io.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module Lisp
|
2
|
+
|
3
|
+
class IO
|
4
|
+
|
5
|
+
def self.register
|
6
|
+
Primitive.register("load") {|args, env| Lisp::IO::load_impl(args, env) }
|
7
|
+
Primitive.register("load-library") {|args, env| Lisp::IO::load_library_impl(args, env) }
|
8
|
+
Primitive.register("load-project") {|args, env| Lisp::IO::load_project_impl(args, env) }
|
9
|
+
Primitive.register("trace") {|args, env| puts "Trace: #{(args.to_a.map {|a| a.evaluate(env).value.to_s}).join(' ')}"; nil}
|
10
|
+
Primitive.register("error") {|args, env| App.alert((args.to_a.map {|a| a.evaluate(env).value.to_s}).join(' '))}
|
11
|
+
Primitive.register("alert") {|args, env| App.alert((args.to_a.map {|a| a.evaluate(env).value.to_s}).join(' '))}
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def self.load_impl(args, env)
|
16
|
+
raise "'load' requires 1 argument." if args.empty?
|
17
|
+
fname = args.car.evaluate(env)
|
18
|
+
raise "'load' requires a string argument." unless fname.string?
|
19
|
+
filename = fname.value.end_with?(".lsp") ? fname.value : "#{fname.value}.lsp"
|
20
|
+
File.open(filename) do |f|
|
21
|
+
contents = f.read()
|
22
|
+
Lisp::Parser.new.parse_and_eval_all(contents)
|
23
|
+
end
|
24
|
+
Lisp::String.with_value("OK")
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def self.load_library_impl(args, env)
|
29
|
+
raise "'load-library' requires 1 argument." if args.empty?
|
30
|
+
library_name = args.car.evaluate(env)
|
31
|
+
raise "'load-library' requires a string or symbol argument." unless library_name.string? || library_name.symbol?
|
32
|
+
Dir.chdir(File.join(App.documents_path, "libraries", "#{library_name}.lib")) do |d|
|
33
|
+
if File.exists?("load.lsp")
|
34
|
+
File.open("load.lsp") do |f|
|
35
|
+
contents = f.read()
|
36
|
+
Lisp::Parser.new.parse_and_eval_all(contents)
|
37
|
+
end
|
38
|
+
else
|
39
|
+
Dir.glob("*.lsp") do |filename|
|
40
|
+
File.open(filename) do |f|
|
41
|
+
contents = f.read()
|
42
|
+
Lisp::Parser.new.parse_and_eval_all(contents)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
Lisp::String.with_value("OK")
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def self.load_project_impl(args, env)
|
52
|
+
raise "'load-project' requires 1 argument." if args.empty?
|
53
|
+
project_name = args.car.evaluate(env)
|
54
|
+
raise "'load-project' requires a string or symbol argument." unless project_name.string? || project_name.symbol?
|
55
|
+
Dir.chdir(File.join(App.documents_path, "projects", "#{project_name}.prj")) do |d|
|
56
|
+
if File.exists?("load.lsp")
|
57
|
+
File.open("load.lsp") do |f|
|
58
|
+
contents = f.read()
|
59
|
+
Lisp::Parser.new.parse_and_eval_all(contents)
|
60
|
+
end
|
61
|
+
else
|
62
|
+
Dir.glob("*.lsp") do |filename|
|
63
|
+
File.open(filename) do |f|
|
64
|
+
contents = f.read()
|
65
|
+
Lisp::Parser.new.parse_and_eval_all(contents)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
Lisp::String.with_value("OK")
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|