3
;;; .logo -- Logo initialization file (v.0.9.0) Hrvoje Blazevic
6
;; Reversing 5.1 changes
7
;; Don't like getter/setter syntax "simplification". .LOOPS is
8
;; slow even without ALLOWGETSET. UNBURYONEDIT is meaningless
9
;; in logo-mode, and can possibly get in the way.
10
make "state.allowgetset :allowgetset
11
make "state.unburyonedit :unburyonedit
12
bury [[] [state.allowgetset state.unburyonedit] []]
13
erase [[] [allowgetset unburyonedit] []]
14
pr [ALLOWGETSET and UNBURYONEDIT disabled]
16
type "|loading LOOPS ... | wait 0
18
;; Allowing changes to Logo primitives
22
;; Preserving original definitions
25
copydef "ifelse.tf "ifelse
29
copydef "test.tf "test
33
erase [if ifelse not and or test]
38
.macro if :tf.val :run.true [:run.false []] 2
39
op (if.tf equalp :tf.val "false [:run.false] [:run.true])
42
.macro ifelse :tf.val :run.true :run.false
43
op (if.tf equalp :tf.val "false [:run.false] [:run.true])
47
op (if.tf equalp :thing.not "false ["true] ["false])
61
to and [:form.and ["true]] [:forms.and] 2
62
if.tf emptyp :forms.and [op run :form.and]
63
if run :form.and [op apply "and :forms.and]
67
to or [:form.or ["false]] [:forms.or] 2
68
if.tf emptyp :forms.or [op run :form.or]
70
op apply "or :forms.or
73
.macro cond.if :#cond.val
74
if :#cond.val [op list "op :#cond.val]
78
to .and [:form.and ["true]] [:forms.and] 2
79
if.tf emptyp :forms.and [op first lput "#unspecified runresult :form.and]
80
if.tf not first lput "#unspecified runresult :form.and [op "false]
81
op apply ".and :forms.and
84
.macro test :any.value
85
op (list "test.tf "not.tf "not quoted :any.value)
88
;;; Extended prefix operators
90
copydef "difference.s "difference
91
copydef "quotient.s "quotient
93
erase [difference quotient equal? greater? less? before?]
95
to difference :first.num [:rest.nums] 2
96
if.tf emptyp :rest.nums [op minus :first.num]
97
op :first.num - (apply "sum :rest.nums)
100
to quotient :first.num [:rest.nums] 2
101
if.tf emptyp :rest.nums [op (1 / :first.num)]
102
op :first.num / (apply "product :rest.nums)
105
to equal? :elt [:rest] 2
106
op emptyp find [not.tf equalp ? :elt] :rest
109
to less? :elt [:nums] 2
110
if.tf emptyp :nums [op "true]
111
if.tf :elt < first :nums [op apply "less? :nums]
115
to greater? :elt [:nums] 2
116
if.tf emptyp :nums [op "true]
117
if.tf greaterp :elt first :nums [op apply "greater? :nums]
121
to before? :wd [:wds] 2
122
if.tf emptyp :wds [op "true]
123
if.tf beforep :wd first :wds [op apply "before? :wds]
127
to lesseq? :elt [:nums] 2
128
if.tf emptyp :nums [op "true]
129
if.tf :elt > first :nums [op "false]
130
op apply "lesseq? :nums
133
to greatereq? :elt [:nums] 2
134
if.tf emptyp :nums [op "true]
135
if.tf lessp :elt first :nums [op "false]
136
op apply "greatereq? :nums
139
to beforeq? :wd [:wds] 2
140
if.tf emptyp :wds [op "true]
141
if.tf beforep first :wds :wd [op "false]
142
op apply "beforeq? :wds
147
;; Prohibit further changes of primitives
150
bury [if ifelse not true false else or and .and test cond.if]
151
bury [difference equal? greater? less? greatereq? lesseq? beforeq? quotient
152
before? difference.s quotient.s]
155
;;; Defining High Level Structures
159
.macro letrec :in.letrec
160
local [body.letrec method.&stack]
161
make "method.&stack []
162
make "body.letrec fput "dummy.letrec (list fput [] bf :in.letrec)
163
op insert.invoke letrec.helper lput :body.letrec first :in.letrec
166
to letrec.helper :clauses.letrec
167
if.tf emptyp :clauses.letrec [op (list "run [(dummy.letrec)])]
168
push "method.&stack first first :clauses.letrec
169
op (se "local (word "" first :method.&stack)
170
"make (word "" first :method.&stack)
171
bf first :clauses.letrec letrec.helper bf :clauses.letrec)
174
to insert.invoke :text
175
if.tf emptyp :text [op []]
176
if.tf wordp first :text [
177
op (or [(and [equalp first :text "\(]
178
[memberp first bf :text :method.&stack]
179
[(se first :text "invoke word ": first bf :text
180
insert.invoke bf bf :text)])]
181
[se first :text insert.invoke bf :text])]
182
op (if.tf listp first :text [fput insert.invoke runparse first :text
183
insert.invoke bf :text]
184
[fput first :text insert.invoke bf :text])
187
;;; Cond -- 2 versions
189
;; universal -- operation and command
190
.macro cond.ifelse :#cond.val :#cond.rest
191
op ifelse :#cond.val [(list :#cond.val)] [:#cond.rest]
194
.macro cond :cond.clauses
195
local [fclauses lclause]
196
make "lclause last :cond.clauses
197
(if.tf and [wordp first :lclause]
198
[memberp first :lclause [else true t]]
199
[make "lclause apply "se bf :lclause
200
make "fclauses bl :cond.clauses]
201
[make "fclauses :cond.clauses make "lclause ["#unspecified]])
202
op cond.helper :fclauses
205
to cond.helper :cond.clauses
206
if.tf emptyp :cond.clauses [op :lclause]
207
if.tf emptyp bf first :cond.clauses [
208
op (se "cond.ifelse first first :cond.clauses
209
(list cond.helper bf :cond.clauses))]
210
op (se "ifelse.tf first first :cond.clauses
211
(list apply "se bf first :cond.clauses)
212
(list cond.helper bf :cond.clauses))
215
;; command only -- slightly faster
216
.macro condc :cond.clauses
217
local [fclauses lclause]
218
make "lclause last :cond.clauses
219
(if.tf and [wordp first :lclause]
220
[memberp first :lclause [else true t]]
221
[make "lclause apply "se bf :lclause
222
make "fclauses bl :cond.clauses]
223
[make "fclauses :cond.clauses make "lclause ["#unspecified]])
224
op condc.helper :fclauses
227
to condc.helper :cond.clauses
228
if.tf emptyp :cond.clauses [op :lclause]
229
if.tf emptyp bf first :cond.clauses [
230
op (se "cond.if first first :cond.clauses
231
condc.helper bf :cond.clauses)]
232
op (se "if.tf first first :cond.clauses
233
(list apply "se bf first :cond.clauses)
234
condc.helper bf :cond.clauses)
239
;; universal -- operation and command, but *must* output a value
241
.macro case :case.clauses
242
local [fclauses lclause]
243
make "lclause last :case.clauses
244
(if.tf and [wordp first :lclause]
245
[memberp first :lclause [else true t]]
246
[make "lclause apply "se bf :lclause
247
make "fclauses bl bf :case.clauses]
248
[make "fclauses bf :case.clauses make "lclause ["#unspecified]])
249
op (se (list "local ""#target "make ""#target "run first :case.clauses)
250
case.helper :fclauses)
253
to case.helper :first.clauses
254
if.tf emptyp :first.clauses [op :lclause]
255
op (se "ifelse.tf "memberp ":#target
256
(list first first :first.clauses)
257
(list apply "se bf first :first.clauses)
258
(list case.helper bf :first.clauses))
263
;; command only -- mix code, true forms do not have to output
264
.macro casec :case.clauses
265
local [fclauses lclause]
266
make "lclause last :case.clauses
267
(if.tf and [wordp first :lclause]
268
[memberp first :lclause [else true t]]
269
[make "lclause apply "se lput [op "#unspecified] bf :lclause
270
make "fclauses bl bf :case.clauses]
271
[make "fclauses bf :case.clauses make "lclause [op "#unspecified]])
272
op (se (list "local ""#target "make ""#target "run first :case.clauses)
273
casec.helper :fclauses)
276
to casec.helper :first.clauses
277
if.tf emptyp :first.clauses [op :lclause]
278
op (se "ifelse.tf "memberp ":#target
279
(list first first :first.clauses)
280
(list apply "se lput [op "#unspecified] bf first :first.clauses)
281
(list casec.helper bf :first.clauses))
285
;;; Compiler -- source is commented out. Only the compiled code gets loaded.
287
; to loops.compiler [:proc procedures] 1
289
; [compile.proc [[proc]
290
; [if emptyp :proc [op []]]
291
; [local "struct.min]
293
; (and [wordp first :proc]
294
; [macrop first :proc]
295
; [not gprop "compiler.cap first :proc]
296
; [not.tf emptyp bf :proc]
297
; [listp first bf :proc])
298
; [make "compiled "true
299
; se (list "run macroexpand list first :proc
300
; (compile.proc first bf :proc))
301
; (compile.proc bf bf :proc)]
302
; [or [and [listp first :proc]
303
; [fput (compile.proc first :proc)
304
; (compile.proc bf :proc)]]
305
; [fput first :proc (compile.proc bf :proc)]]]]]
306
; [compile.ws [[proc.lst compiled]
307
; [if.tf emptyp :proc.lst [stop]]
308
; [.type (se "compiling first :proc.lst "|... |)]
310
; [(invoke (or [and [macrop first :proc.lst]
313
; first :proc.lst (compile.proc text first :proc.lst))]
314
; [.pr (if.tf :compiled
315
; [.and [pprop "compiled.procs first :proc.lst "true]
317
; [(se [nothing to do for] first :proc.lst)])]
318
; [(compile.ws bf :proc.lst "false)]]]]
319
; [ifelse listp :proc [(compile.ws filter "procedurep :proc "false)]
320
; [(compile.ws filter "procedurep (list :proc) "false)]]
321
; [.pr [compilation completed]]]
324
;;; Invoking the compiler from logo-mode with Compile Workspace
326
;; Using ws.compile instead of loops.compiler
327
;; Filtering out all procedure names that end with .class
328
;; Compiling Class templates, firstly makes no sense, secondly,
329
;; will make Class unusable to the OBJECT.MAKER
337
[[x] [make "split split.word :x ".
338
op not (and [1 < count :split]
339
[equalp last :split "class])]]
343
to compile.object :text
344
if.tf emptyp :text [op []]
345
if.tf (and [wordp first :text]
347
[not gprop "compiler.cap first :text]
348
[not.tf emptyp bf :text]
349
[listp first bf :text]) ~
350
[op se (list "run macroexpand list first :text
351
compile.object first bf :text)
352
compile.object bf bf :text]
353
if.tf listp first :text ~
354
[op fput compile.object first :text compile.object bf :text]
355
op fput first :text compile.object bf :text
359
if.tf :.verbose [type :text]
363
if.tf :.verbose [pr :text]
366
;; specifying compiler output
369
;; Saving *only* compiled procedures.
371
to save.compiled [:filename .and
372
[type "|Enter file name to save to: |]
374
if.tf namep "printwidthlimit ~
375
[localmake "width :printwidthlimit ern "printwidthlimit]
376
if.tf namep "printdepthlimit ~
377
[localmake "depth :printdepthlimit ern "printdepthlimit]
378
if equalp first :filename "" [make "filename bf :filename]
380
make "oldwriter writer
383
po (filter [[proc] [op not.tf emptyp gprop "compiled.procs :proc]]
387
if.tf namep "width [make "printwidthlimit :width]
388
if.tf namep "depth [make "printdepthlimit :depth]
392
;;; Compiler Capabilities
394
;;; Capabilities have this format: property = name of High Level Procedure
397
;;; You can add your own compiler capabilities, providing you follow
398
;;; these rules: High level procedure (structure) you define must have
399
;;; one input only - a list. And, of-course it must be a macro --
400
;;; otherwise there is nothing for compiler to do. After you have
401
;;; defined (and tested) your procedure add your pprop line to lines
402
;;; below. That is all.
404
pprop "compiler.cap "letrec "false
405
pprop "compiler.cap "cond "false
406
pprop "compiler.cap "condc "false
407
pprop "compiler.cap "case "false
408
pprop "compiler.cap "casec "false
410
bury [[insert.invoke letrec letrec.helper cond cond.helper loops.compiler
411
compile.object save.compiled case .pr case.helper
412
casec casec.helper .type ws.compile condc condc.helper
414
[.verbose] [compiler.cap compiled.procs]]
416
;;; End of interpreter changes (.logo)
419
;;; Additions to Logo library
421
to before :first.wd [:rest.wds] 2
422
if emptyp :rest.wds [op :first.wd]
423
if beforep first :rest.wds :first.wd [op apply "before :rest.wds]
424
op apply "before fput :first.wd bf :rest.wds
427
to max :first [:rest] 2
428
if emptyp :rest [op :first]
429
if greaterp :first first :rest [op apply "max fput :first bf :rest]
433
to min :first [:rest] 2
434
if emptyp :rest [op :first]
435
if lessp :first first :rest [op apply "min fput :first bf :rest]
440
op zerop remainder :number 2
443
copydef "even? "evenp
455
copydef "zero? "zerop
462
if emptyp bf :lst [op :lst]
466
to split.word :string [:delimiter "\ ] 2
468
if emptyp :string [op (list ")]
469
make "result split.word bf :string :delimiter
470
if equalp first :string :delimiter [op fput " :result]
471
op fput word first :string first :result bf :result
474
to time :instruction.list
475
localmake "start first first shell [date "+%s"]
476
pr runresult :instruction.list
477
(pr "Elapsed "time: (first first shell [date "+%s"]) - :start "seconds)
480
.macro begin :begin.forms
481
op apply "se :begin.forms
484
bury [before max min evenp even? oddp odd? zerop zero? identity last.pair
485
split.word time begin]
487
;;; Restoring Standard Berkeley Logo
488
;;; This is of practical value only if used within Emacs logo-mode
493
copydef "ifelse "ifelse.tf
497
copydef "test "test.tf
498
copydef "difference "difference.s
499
copydef "quotient "quotient.s
500
copydef "equal? "equalp
501
copydef "greater? "greaterp
502
copydef "less? "lessp
503
copydef "before? "beforep
505
make "allowgetset :state.allowgetset
506
make "unburyonedit :state.unburyonedit
507
bury [[] [allowgetset unburyonedit] []]
509
[if.tf ifelse.tf not.tf and.tf or.tf test.tf false else t true .and
510
insert.invoke letrec letrec.helper cond cond.helper cond.if
511
cond.ifelse condc condc.helper loops.compiler ws.compile
512
save.compiled case case.helper difference.s quotient.s lesseq?
513
greatereq? beforeq? .type .pr casec casec.helper begin]
514
[.verbose state.allowgetset state.unburyonedit]
515
[compiler.cap compiled.procs]]
518
[object.maker static.make compile.object bucket.class base.object
519
counter.class send rewinding.counter.class container.class
520
stack.class delegate #self border.class browse.classes
521
circular.class double.end.class edit.classes indirect
522
inherit inherit.from insert.method insert.tree
523
inspect.methods.objects lambda list.class loops new
524
objects.group pair.class queue.class save.image send.helper
525
show.method.object static swap.pair.class word.class]
526
[.accept.method loops.object.stack] [inheritance.tree]]
528
gc ignore nodes gc ignore nodes gc
529
pr [Standard Berkeley Logo restored.]
532
bury [restore.standard loops.compiler]
537
to loops.compiler [:proc procedures] 1
538
run [local "compile.proc make "compile.proc [[proc] [if emptyp :proc [op []]] [local "struct.min] [op ifelse.tf ( and [wordp first :proc] [macrop first :proc] [not gprop "compiler.cap first :proc] [not.tf emptyp bf :proc] [listp first bf :proc] ) [make "compiled "true se ( list "run macroexpand list first :proc ( invoke :compile.proc first bf :proc ) ) ( invoke :compile.proc bf bf :proc )] [or [and [listp first :proc] [fput ( invoke :compile.proc first :proc ) ( invoke :compile.proc bf :proc )]] [fput first :proc ( invoke :compile.proc bf :proc )]]]] local "compile.ws make "compile.ws [[proc.lst compiled] [if.tf emptyp :proc.lst [stop]] [.type ( se "compiling first :proc.lst "|... | )] [wait 0] [( invoke ( or [and [macrop first :proc.lst] [".defmacro]] ["define] ) first :proc.lst ( invoke :compile.proc text first :proc.lst ) )] [.pr ( if.tf :compiled [.and [pprop "compiled.procs first :proc.lst "true] ["OK]] [( se [nothing to do for] first :proc.lst )] )] [( invoke :compile.ws bf :proc.lst "false )]] local "dummy.letrec make "dummy.letrec [[] [ifelse listp :proc [( invoke :compile.ws filter "procedurep :proc "false )] [( invoke :compile.ws filter "procedurep ( list :proc ) "false )]] [.pr [compilation completed]]] run [( invoke :dummy.letrec )]]
541
type [Lisp layer OK ...]