OpenCores
URL https://opencores.org/ocsvn/igor/igor/trunk

Subversion Repositories igor

[/] [igor/] [trunk/] [microprogram_assembler/] [bootprogram.lisp] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 atypic
;;;
2
(in-package #:sexptomem)
3
 
4
(sexp-to-memory*
5
  (%nil
6
   %t
7
   %if
8
   %quote
9
   %lambda
10
   %progn
11
   %cons
12
   %car
13
   %cdr
14
   %eval
15
   %apply
16
   %type
17
   %make-array
18
   %array-size
19
   %array-get
20
   %array-set
21
   %make-symbol
22
   %symbol-to-string
23
   %char-to-int
24
   %int-to-char
25
   %get-char
26
   %put-char
27
   %num-devices
28
   %device-type
29
   %set-address
30
   %get-address
31
   %error
32
   %add
33
   %sub
34
   %mul
35
   %div
36
   %bitwise-and
37
   %bitwise-or
38
   %bitwise-not
39
   %bitwise-shift
40
   %current-environment
41
   %make-eval-state
42
   %eval-partial
43
   %define
44
   %undefine
45
   %eq?
46
   %num-eq?
47
   %char-eq?
48
   %less-than?
49
   %mod
50
   %set!
51
   %set-car!
52
   %set-cdr!
53
   %function-data
54
   %builtin-name
55
   %device-size
56
   %device-status
57
 
58
   xxxaa
59
   xxxab
60
   xxxac
61
   xxxad
62
   xxxae
63
   xxxaf
64
   xxxag
65
   xxxah
66
   xxxai
67
   xxxaj
68
   xxxak
69
 
70
   %symbol-table
71
 
72
   %phase-eval
73
   %phase-eval-args
74
   %phase-apply
75
   %phase-eval-if
76
   %phase-initial
77
   %phase-env-lookup
78
   %phase-env-lookup-local
79
   %phase-apply-function
80
   %phase-bind-args
81
   %phase-eval-progn
82
   %phase-eval-args-top
83
   %phase-eval-args-cdr
84
   %phase-eval-args-cons
85
   %phase-eval-symbol
86
   %phase-set!
87
 
88
   xxx3F
89
 
90
   %timeout
91
   %err-invalid-phase
92
   %err-unbound-symbol
93
   %err-invalid-param-list
94
   %err-too-few-args
95
   %err-too-many-args
96
   %err-invalid-state
97
   %err-invalid-arg-list
98
   %err-type-error
99
   %err-not-a-list
100
   %err-not-a-function
101
   %err-invalid-function
102
   %err-malformed-form
103
   %err-invalid-builtin
104
   %err-invalid-array-index
105
   %err-invalid-env
106
   %err-not-a-pair
107
   %err-division-by-zero
108
   %err-overflow
109
   )
110
 
111
  (%progn
112
 
113
   (%progn                              ; Define types
114
    (%define '+type-none+ #x0)
115
    (%define '+type-int+ #x1)
116
    (%define '+type-float+ #x3)
117
    (%define '+type-cons+ #x4)
118
    (%define '+type-snoc+ #x5)
119
    (%define '+type-ptr+ #x6)
120
    (%define '+type-array+ #x7)
121
    (%define '+type-nil+ #x8)
122
    (%define '+type-t+ #x9)
123
    (%define '+type-char+ #xA)
124
    (%define '+type-symbol+ #xB)
125
    (%define '+type-function+ #xC)
126
    (%define '+type-builtin+ #xD)
127
    )
128
 
129
   (%define 'current-input 2)
130
   (%define 'current-output 2)
131
 
132
   (%define '*print-base* 16)
133
 
134
   (%define '1+ (%lambda 1+ (x)
135
                         (%add 1 x)))
136
 
137
   (%define '1- (%lambda 1- (x) (%sub x 1)))
138
 
139
   (%define 'map (%lambda map (fn list)
140
                          (%if list
141
                               (%cons (fn (%car list))
142
                                      (map fn (%cdr list)))
143
                               %nil)))
144
 
145
   (%define 'map-short (%lambda map-short (fn list)
146
                                (%if list
147
                                     (%cons (fn (%car list))
148
                                            (map fn (%cdr list)))
149
                                     %nil)))
150
 
151
 
152
   (%define 'list (%lambda list list list))
153
 
154
   (%define 'char-upper (%lambda char-upper (char)
155
                                 (let ((n (%char-to-int char)))
156
                                   (%if (%less-than? (1- (%char-to-int #\a)) n)
157
                                        (%if (%less-than? n (1+ (%char-to-int #\z)))
158
                                             (%int-to-char (%sub n 32))
159
                                             char)
160
                                        char))))
161
 
162
   (%define 'make-string-stream (%lambda make-string-stream (str pos)
163
                                         (%lambda string-stream (cmd)
164
                                                  (%if (%eq? cmd 'get-char)
165
                                                       (%if (%less-than? (1- (%array-size str)) pos)
166
                                                            'eos
167
                                                            (%progn
168
                                                             (%set! 'pos (1+ pos))
169
                                                             (%array-get str (1- pos))))
170
                                                       (%if (%eq? cmd 'peek-char)
171
                                                            (%if (%less-than? (1- (%array-size str)) pos)
172
                                                                 'eos
173
                                                                 (%array-get str pos))
174
                                                            %nil)))))
175
 
176
   (%define 'make-device-input-stream (%lambda make-device-input-stream (device-number)
177
                                               (let ((chpeek %nil))
178
                                                 (%lambda device-input-stream (cmd)
179
                                                          (%if (%eq? cmd 'get-char)
180
                                                               (let ((thech (%if chpeek
181
                                                                                 (let ((ch chpeek))
182
                                                                                   (%set! 'chpeek %nil)
183
                                                                                   ch)
184
                                                                                 (%get-char device-number))))
185
                                                                 (%if (or2 (%num-eq? device-number 2) (%num-eq? device-number 0))
186
                                                                      (%put-char current-output thech)
187
                                                                      %nil)
188
                                                                 thech)
189
                                                               (%if (%eq? cmd 'peek-char)
190
                                                                    (%if chpeek
191
                                                                         chpeek
192
                                                                         (%set! 'chpeek (%get-char device-number)))
193
                                                                    %nil))))))
194
 
195
 
196
 
197
 
198
 
199
   (%define
200
    'stream-wrapper-narwhal
201
    (%lambda stream-wrapper-narwhal (stream)
202
             (let ((chpeek %nil))
203
               (%lambda input-stream (cmd)
204
                        (%if (%eq? cmd 'get-char)
205
                             (%if chpeek
206
                                 (let ((chkeep chpeek))
207
                                   (%set! 'chpeek %nil)
208
                                   chkeep)
209
                                 (stream 'get-char))
210
                             (%if (%eq? cmd 'peek-char)
211
                                  (%if chpeek
212
                                       chpeek
213
                                       (%set! 'chpeek (stream 'get-char)))
214
                                  (%error 'I-<3-YOU-STREAM-WRAPPER)))))))
215
 
216
   ;Code for reading the filesystem
217
   ;Filetable first, each entry has [in use, filename, start-block, length]
218
   ;Then comes one word per block, which is rather hilarious usage of space...
219
   ;... "meta-info" about blocks, we'll call it. suuure.
220
   ;Then comes the blocks. Each block is some size. A block has a pointer to
221
   ;the next block that follows it.
222
 
223
;The fileinfo (file identifier) passed around.
224
   (%define '+fileinfo-num-fields+ 6)
225
   (%define '+fileinfo-name+ 0)
226
   (%define '+fileinfo-tableindex+ 1)
227
   (%define '+fileinfo-block+ 2)
228
   (%define '+fileinfo-block-pos+ 3)
229
   (%define '+fileinfo-current-pos+ 4)
230
   (%define '+fileinfo-size+ 5)
231
 
232
;The metadata structure.
233
   (%define '+metadata-pos+ 0)
234
   (%define '+metadata-size+ 16)
235
   (%define '+metadata-num-blocks+ 0)
236
   (%define '+metadata-free-blocks+ 1)
237
   (%define '+metadata-blocksize+ 2)
238
   (%define '+metadata-block-pos+ 3)
239
   (%define '+metadata-ft-num-rows+ 4) ;number of filetable rows
240
   (%define '+metadata-ft-free-rows+ 5) ;number of free rows
241
   (%define '+metadata-ft-rowsize+ 6) ;size of a filetable row
242
   (%define '+metadata-ft-pos+ 7) ;position of filetable (absolute address)
243
 
244
;The filetable structure and various values
245
   (%define '+filetable-pos+ 16)
246
   (%define '+filetable-field-size+ 16)
247
   (%define '+filetable-num-rows+ 2)
248
   (%define '+filetable-size+ 32)
249
   (%define '+filetable-not-in-use-marker+ 0)
250
   (%define '+filetable-field-in-use+ 0)
251
   (%define '+filetable-field-filename+ 1)
252
   (%define '+filetable-field-start-block+ 14)
253
   (%define '+filetable-field-filesize+ 15)
254
   (%define '+filename-size+ 13)
255
 
256
;The blocktale structure
257
   (%define '+blocktable-pos+ 48)
258
   (%define '+blocktable-size+ 8)
259
 
260
;Various defines partaining to blocks
261
   (%define '+block-section-pos+ 56)
262
   (%define '+block-size+ 8)
263
   (%define '+num-blocks+ 8)
264
 
265
 
266
;The device used for storage
267
   (%define '+storage-dev+ 1)
268
 
269
 
270
    ;get the ith entry from the filetable, put it in an array
271
   (defun filetable-entry (index)
272
     (get-string
273
      (address-of-entry index)
274
      (metadata +metadata-ft-rowsize+)))
275
 
276
   (%define '+file-null-char+ 4)
277
 
278
   ;should've had array-append...
279
   (defun count-non-null* (s pos num)
280
     (%if (%num-eq?
281
           (%array-size s)
282
           pos)
283
          num
284
          (%if (%num-eq?
285
                +file-null-char+
286
                (%char-to-int (%array-get s pos)))
287
               (count-non-null* s (1+ pos) num)
288
               (count-non-null* s (1+ pos) (1+ num)))))
289
   (defun count-non-null (s)
290
     (count-non-null* s 0 0))
291
 
292
 
293
 
294
   (defun strip-null (s)
295
     (array-resize s (count-non-null s)))
296
 
297
 
298
 
299
 
300
   (defun array-resize* (new arr size pos)
301
     (%if (%num-eq?
302
           size
303
           pos)
304
          new
305
          (%progn
306
           (%array-set new pos (%array-get arr pos))
307
           (array-resize* new arr size (1+ pos)))))
308
 
309
   (defun array-resize (arr size)
310
     (let ((new (%make-array size %nil)))
311
       (array-resize* new arr size 0)))
312
 
313
 
314
 
315
 
316
 
317
 
318
   (defun str-eq?* (f1 f2 pos)
319
     (%if
320
      (%num-eq? (%array-size f1) pos)
321
      %t
322
      (%if (%char-eq?
323
            (%array-get f1 pos)
324
            (%array-get f2 pos))
325
           (str-eq?* f1 f2 (1+ pos))
326
           %nil)))
327
 
328
  (defun str-eq? (f1 f2)
329
    (%if (%num-eq? (%array-size f1) (%array-size f2))
330
         (str-eq?* f1 f2 0)
331
         %nil))
332
 
333
   ;slice of a part of an array of chars [tested ok...]
334
   (%define
335
    'string-slice*
336
    (%lambda
337
     string-slice* (str slice stringpos pos len)
338
     (%if (%num-eq? pos len)
339
          slice
340
          (%progn
341
           (%array-set slice pos (%array-get str stringpos))
342
           (string-slice* str slice (1+ stringpos) (1+ pos) len)))))
343
 
344
   (%define
345
    'string-slice
346
    (%lambda
347
     string-slice (str start len)
348
     (let ((slice (%make-array len %nil)))
349
       (string-slice* str slice start 0 len))))
350
 
351
 
352
   ;get the filename of an entry in the filetable
353
   (%define
354
    'filetable-entry-filename
355
    (%lambda filetable-entry-filename (filetable-entry)
356
             (string-slice
357
              filetable-entry
358
              +filetable-field-filename+
359
              +filename-size+)))
360
 
361
   (%define
362
    'filetable-entry-block
363
    (%lambda filetable-entry-block (filetable-entry)
364
             (%char-to-int
365
              (%array-get filetable-entry +filetable-field-start-block+))))
366
 
367
   (%define
368
    'filetable-entry-size
369
    (%lambda filetable-entry-size (filetable-entry)
370
             (%char-to-int
371
              (%array-get filetable-entry +filetable-field-filesize+))))
372
 
373
 
374
 
375
   (defun filetable-entry-in-use (entry)
376
     (%if (%num-eq?
377
           (%char-to-int (%array-get entry +filetable-field-in-use+))
378
           0)
379
          %nil
380
          %T))
381
                                        ;Get the starting block of the file at index in filetable
382
   (%define
383
    'filetable-start-block
384
    (%lambda filetable-start-block (index)
385
             (%progn
386
              (%set-address +storage-dev+ 0)
387
              (%char-to-int (%get-char (%add
388
                                       (%mul +filetable-field-size+ index)
389
                                       +filetable-field-start-block+))))))
390
 
391
                                        ;Get the size of the file at index in the filetable
392
   (%define
393
    'filetable-filesize
394
    (%lambda filetable-filesize
395
             (%set-address +storage-dev+ 0)
396
             (%char-to-int (%get-char (%add
397
                                       (%mul +filetable-field-size+ index)
398
                                       +filetable-field-filesize+)))))
399
 
400
   ;put length chars from starting-position into an array of length size
401
   (defun get-string* (str len pos)
402
     (%if (%num-eq? pos len)
403
          str
404
          (%progn
405
           (%array-set str pos (%get-char +storage-dev+))
406
           (get-string* str len (1+ pos)))))
407
 
408
 
409
   (defun get-string (start-pos length)
410
     (let ((string (%make-array length %nil)))
411
       (%set-address +storage-dev+ start-pos)
412
       (get-string* string length 0)))
413
 
414
 
415
   (defun put-string* (src len pos)
416
     (%if (%num-eq? pos len)
417
          src
418
          (%progn
419
           (%put-char +storage-dev+ (%array-get src pos))
420
           (put-string* src len (1+ pos)))))
421
 
422
   (defun put-string (dst string)
423
     (%set-address +storage-dev+ dst)
424
     (put-string* string (%array-size string) 0))
425
 
426
    ;iterate file-table, find matching filename and return the fileinfo-entry, used by streams
427
   (defun open-file* (filename file-info index)
428
     (%if (%num-eq?
429
           (metadata +metadata-ft-num-rows+)
430
           index)
431
          (display "No such file or filename. IGOR is not happy, making him work this much...")
432
 
433
          (let ((entry (filetable-entry index))) ;get ith entry in filetable
434
            (%if (filetable-entry-in-use entry)
435
                 (let ((entry-filename (strip-null (filetable-entry-filename entry)))) ;store filename
436
                   (%if (str-eq? entry-filename filename) ;compare filenames, if equal:
437
                        (%progn
438
                                        ;create a file-info structure
439
                    (%array-set file-info +fileinfo-name+ entry-filename)
440
                    (%array-set file-info +fileinfo-block+ (filetable-entry-block entry))
441
                    (%array-set file-info +fileinfo-size+ (filetable-entry-size entry))
442
                    file-info)
443
                                        ;filename mismatch, next entry please
444
                        (open-file* filename file-info (1+ index))))
445
                 (open-file* filename file-info (1+ index)))))) ;entry not in use, next.
446
 
447
   (defun open-file (filename)
448
     (let ((file-info (%make-array +fileinfo-num-fields+ 0)))
449
       (open-file* filename file-info 0)))
450
 
451
 
452
 
453
 
454
   (defun filetable-get-offset (filename index)
455
     (let ((current-filename (get-string
456
                              (%add
457
                               +filetable-field-fieldname+ (%mul
458
                                                            index
459
                                                            +filetable-field-size+))
460
                              +filename-size+)))))
461
 
462
 
463
 
464
   (defun file-address (file-info)
465
     (%add
466
      (address-of-block (%array-get file-info +fileinfo-block+))
467
      (%array-get file-info +fileinfo-block-pos+)))
468
 
469
   (%define
470
    'make-fisk-stream
471
    (%lambda make-fisk-stream (open-fisk-dings)
472
             (stream-wrapper-narwhal
473
              (%lambda fisk-stream (cmd)
474
                       (%if (%eq? cmd 'get-char)
475
                           (file-get-char open-fisk-dings))))))
476
 
477
 
478
   (%define
479
    'file-eof?
480
    (%lambda file-eof? (file-info)
481
             (%if (%eq?
482
                   (%array-get file-info +fileinfo-current-pos+)
483
                   (%array-get file-info +fileinfo-size+))
484
                  %t
485
                  %nil)))
486
   (%define
487
    'file-get-char
488
    (%lambda file-get-char (file-info)
489
             (%if (file-eof? file-info)
490
                  (%error 'EOF)
491
                  (let ((ch (file-read-char file-info)))
492
 
493
                    (file-increment-pos file-info)
494
                    ch))))
495
 
496
 
497
   (%define
498
    'file-read-char
499
    (%lambda file-read-char (file-info)
500
             (%progn
501
              (%set-address +storage-dev+ (file-address file-info))
502
              (%get-char +storage-dev+))))
503
 
504
   (%define
505
    'file-increment-pos
506
    (%lambda file-increment-pos (file-info)
507
             (%if (file-eof? file-info) ;if we're at the end of the file...
508
                  %nil ;...don't increment
509
                  (%progn
510
                   (%array-set   ;else, increment the current-position by 1
511
                    file-info
512
                    +fileinfo-current-pos+
513
                    (1+ (%array-get file-info +fileinfo-current-pos+)))
514
                   (%if (end-of-block file-info) ;if end of block...
515
                        (%progn
516
                         (%array-set
517
                          file-info
518
                          +fileinfo-block+
519
                          (file-next-block
520
                           (%array-get file-info +fileinfo-block+))) ;find the next block and set
521
                         (%array-set
522
                          file-info
523
                          +fileinfo-block-pos+
524
                          0)) ;and set the current inter-block-position to 0
525
                        (%array-set  ;else, we're not at the end of the block.
526
                         file-info
527
                         +fileinfo-block-pos+
528
                         (1+ (%array-get file-info +fileinfo-block-pos+)))))))) ; simply update current block
529
 
530
 
531
   (%define
532
    'end-of-block
533
    (%lambda end-of-block (file-info)
534
             (%if (%num-eq?
535
                   (%array-get file-info +fileinfo-block-pos+)
536
                   (%sub +block-size+ 2))
537
                  %t
538
                  %nil);not end of block
539
             ))
540
 
541
 
542
   (%define
543
    'file-next-block
544
    (%lambda file-next-block (current-block)
545
             (%progn
546
              (%set-address
547
               +storage-dev+
548
               (%add
549
                (address-of-block current-block)
550
                (1- +block-size+)))
551
              (%char-to-int (%get-char +storage-dev+)))))
552
 
553
   (defun address-of-block (bloc)
554
     (%add
555
      +block-section-pos+
556
      (%mul +block-size+ bloc)))
557
 
558
 
559
   (defun list-files* (index)
560
     (%if (%num-eq?
561
           index
562
           +filetable-num-rows+)
563
          %T
564
          (let ((entry (filetable-entry index)))
565
            (%if (filetable-entry-in-use entry)
566
                 (%progn
567
                  (display (strip-null (filetable-entry-filename entry)))
568
                  (newline)
569
                  (list-files* (1+ index)))
570
                 (list-files* (1+ index))))))
571
 
572
   (defun list-files ()
573
     (list-files* 0))
574
 
575
 
576
   (defun metadata (num)
577
     (%set-address +storage-dev+ (%add +metadata-pos+ num))
578
     (%char-to-int (%get-char +storage-dev+)))
579
 
580
   ;Code for writing to the filesystem is below.
581
   (defun create-file (filename)
582
     (let ((entry (filetable-free-entry)))
583
       (let ((addr (address-of-entry entry)))
584
         (put-char-at-addr addr (%int-to-char 1))
585
         (put-string (%add
586
                      addr
587
                      +filetable-field-filename+)
588
                     filename)
589
         (put-char-at-addr (%add
590
                            addr
591
                            +filetable-field-start-block+)
592
                           (%int-to-char (find-free-block)))
593
         (put-char-at-addr (%add
594
                            addr
595
                            +filetable-field-filesize+)
596
                           (%int-to-char 0))))
597
     (open-file filename))
598
 
599
   (defun put-char-at-addr (addr char)
600
     (%set-address +storage-dev+ addr)
601
     (%put-char +storage-dev+ char))
602
 
603
 
604
     (defun address-of-entry (entry)
605
       (%add
606
        (%mul
607
         entry
608
         (metadata +metadata-ft-rowsize+))
609
        (metadata +metadata-ft-pos+)))
610
 
611
   ;DOES: Attempts to find a free entry in the file table.
612
   ;THROWS: 'filetable-full
613
   (defun filetable-free-entry ()
614
     (%if (%num-eq? (metadata +metadata-ft-free-rows+) 0)
615
          (%error 'filetable-meta-full)
616
          (filetable-free-entry* 0)))
617
   (defun filetable-free-entry* (index)
618
     (%if
619
      (%num-eq?
620
       index
621
       (metadata +metadata-ft-num-rows+))
622
      (%error 'filetable-full)
623
      (%if  ;if this entry is not in use
624
       (%num-eq?
625
        (%char-to-int (%array-get (filetable-entry index) +filetable-field-in-use+))
626
        +filetable-not-in-use-marker+);...eh
627
       index ;return the index.
628
       (filetable-free-entry* (1+ index)))))
629
 
630
 
631
 
632
   (defun find-free-block* (index)
633
     (%if
634
      (%num-eq?
635
       (metadata +metadata-num-blocks+)
636
       index)
637
      %nil
638
      (%progn
639
       (%set-address +storage-dev+ (%add +blocktable-pos+ index))
640
       (%if
641
        (%num-eq?
642
         (%char-to-int (%get-char +storage-dev+))
643
         0)
644
        index
645
        (find-free-block* (1+ index))))))
646
 
647
   (defun find-free-block ()
648
     (%if
649
      (%num-eq?
650
       (metadata +metadata-free-blocks+)
651
       0)
652
      (%error 'no-free-blocks)
653
      (find-free-block* 0)))
654
 
655
 
656
 
657
   (defun set-block-unfree '()
658
     (display "cannot unfree what has been unseen"))
659
   (defun set-block-free '()
660
     (display "setting a block free!"))
661
 
662
 
663
 
664
   (defun write-filetable-entry (fileinfo)
665
     (let ((entry (filetable-find-free-entry)))))
666
 
667
 
668
   (%define 'string=-rec (%lambda string=-rec (i s1 s2)
669
                                  (%if (%num-eq? i (%array-size s1))
670
                                       %t
671
                                       (%if (%char-eq? (%array-get s1 i)
672
                                                       (%array-get s2 i))
673
                                            (string=-rec (1+ i) s1 s2)
674
                                            %nil))))
675
 
676
   (%define 'string=? (%lambda string=? (s1 s2)
677
                               (%if (%num-eq? (%array-size s1) (%array-size s2))
678
                                    (string=-rec 0 s1 s2)
679
                                    %nil)))
680
 
681
   (%define 'symbol-exists?-rec (%lambda symbol-exists?-rec (symbol-table str)
682
                                         (%if symbol-table
683
                                              (%if (string=? (%symbol-to-string (%car symbol-table)) str)
684
                                                   (%car symbol-table)
685
                                                   (symbol-exists?-rec (%cdr symbol-table) str))
686
                                              %nil)))
687
 
688
   ;; Check if a symbol is interned
689
   (%define 'symbol-exists? (%lambda symbol-exists? (str)
690
                                     (symbol-exists?-rec %symbol-table str)))
691
 
692
   ;; Intern a symbol, if it is already intered, just return the symbol
693
   (%define 'intern (%lambda intern (str)
694
                             (let ((sym (symbol-exists? str)))
695
                               (%if sym sym
696
                                    (let ((sym (%make-symbol str)))
697
                                      (%set! '%symbol-table (%cons sym %symbol-table))
698
                                      sym)))))
699
 
700
   (%define
701
    'intern-char-hash
702
    (%lambda
703
     intern-char-hash (ch)
704
     (%bitwise-and (%char-to-int ch) 7)))
705
 
706
   (%define
707
    'intern-make-node
708
    (%lambda
709
     intern-make-node ()
710
     (%cons nil (%make-array 8 nil))))
711
 
712
   (%define
713
    'intern-get-node
714
    (%lambda
715
     intern-get-node (tab hash)
716
     (%array-get
717
      (%if (%array-get tab hash)
718
           tab
719
           (%array-set tab hash (intern-make-node)))
720
      hash)))
721
 
722
   (%define
723
    'intern-get-sym-in-list
724
    (%lambda
725
     intern-get-sym-in-list (str list)
726
     (%if list
727
          (%if (string=? (%symbol-to-string (%car list)) str)
728
               (%car list)
729
               (intern-get-sym-in-list str (%cdr list)))
730
          nil)))
731
 
732
   (%define
733
    'intern-rec
734
    (%lambda
735
     intern-rec (str i tree existing-symbol)
736
     (%if (%num-eq? i (%array-size str))
737
          (let ((sym (intern-get-sym-in-list str (%car tree))))
738
            (%if sym sym
739
                 (%car (%set-car! tree (%cons (%if existing-symbol
740
                                                   existing-symbol
741
                                                   (%make-symbol str))
742
                                              (%car tree))))))
743
          (intern-rec
744
           str
745
           (%add i 1)
746
           (intern-get-node (%cdr tree) (intern-char-hash (%array-get str i)))
747
           existing-symbol))))
748
 
749
   (%define 'symbol-tree (intern-make-node))
750
 
751
   (%define
752
    'intern-foo
753
    (%lambda
754
     intern (str)
755
     (intern-rec str 0 symbol-tree nil)))
756
 
757
   (%define
758
    'intern-symbols
759
    (%lambda
760
     intern-symbols (list)
761
     (%if list
762
          (%progn (intern-rec (%symbol-to-string (%car list)) 0 symbol-tree (%car list))
763
                  (intern-symbols (%cdr list)))
764
          nil)))
765
 
766
 
767
   ;; See if an element member of a list
768
   (%define 'member (%lambda member (elem list test)
769
                             (%if list
770
                                  (%if (test (%car list) elem)
771
                                       %t
772
                                       (member elem (%cdr list) test))
773
                                  %nil)))
774
 
775
   ;; Or functions
776
   ;; XXX: Special form
777
   (%define 'or2 (%lambda or2 (a b)     ; XXX: Special forms
778
                          (%if a a b)))
779
   (%define 'or3 (%lambda or3 (a b c)
780
                          (or2 a (or2 b c))))
781
 
782
   (%define 'digits (%%list #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
783
   (%define 'digits-hex (%cons #\a (%cons #\b (%cons #\c (%cons #\d (%cons #\e (%cons #\f
784
                                                                                      (%cons #\A (%cons #\B (%cons #\C (%cons #\D (%cons #\E (%cons #\F digits)))))))))))))
785
 
786
 
787
   ;; Special characters
788
   ;; These will never be in a symbol
789
   (%define 'special (%%list #\( #\) #\Space))
790
 
791
   ;; Convert a digit character to a digit
792
   (%define 'char-to-digit (%lambda char-to-digit (ch)
793
                                    (%sub (%char-to-int ch) 48)))
794
 
795
   ;; Is the character something we want in our symbol?
796
   (%define 'isalpha? (%lambda isalpha? (ch)
797
                               (%if (member ch special %char-eq?)
798
                                    %nil
799
                                    (%if (member ch digits %char-eq?)
800
                                         %nil
801
                                         %t))))
802
 
803
   ;; Convert a
804
   (%define 'parse-integer* (%lambda parse-integer* (list num radix)
805
                                     (%if list
806
 
807
 
808
                                          (parse-integer* (%cdr list) (%add (%mul num radix) (char->digit (%car list))) radix)
809
                                          num)))
810
   (%define 'parse-integer (%lambda parse-integer (list)
811
                                    (parse-integer* list 0 10)))
812
 
813
   ;; Is the character a whitespace
814
   (%define 'whitespace? (%lambda whitespace? (ch)
815
                                  (or3 (%char-eq? ch #\Space)
816
                                       (%char-eq? ch #\Return)
817
                                       (%char-eq? ch #\Newline))))
818
 
819
   ;; Length of a list
820
   (%define 'length (%lambda length (list)
821
                             (%if list
822
                                  (1+ (length (%cdr list)))
823
                                  0)))
824
 
825
   ;; Convert a list to an array
826
   (%define 'list->string* (%lambda list->string* (list str pos)
827
                                    (%if list
828
                                         (%progn
829
                                          (%array-set str pos (%car list))
830
                                          (list->string* (%cdr list) str (1+ pos)))
831
                                         str)))
832
   (%define 'list->string (%lambda list->string (list)
833
                                   (let ((str (%make-array (length list) #\Space)))
834
                                     (list->string* list str 0))))
835
 
836
   ;; Skip whitespace characters from an input stream
837
   (%define 'skip-whitespace (%lambda skip-whitespace (s)
838
                                      (let ((ch (s (%quote peek-char))))
839
                                        (%if (%eq? ch 'eos)
840
                                             ch
841
                                             (%if (whitespace? ch)
842
                                                  (%progn
843
                                                   (s 'get-char)
844
                                                   (skip-whitespace s))
845
                                                  ch)))))
846
 
847
   ;; Tokenize a symbol
848
   (%define 'tokenize-sym (%lambda tokenize-sym (s ch)
849
                                   (%progn
850
                                    (let ((type
851
                                           (%if (member ch digits %char-eq?)
852
                                                'integer
853
                                                'symbol)))
854
                                      (%define 'tknz
855
                                               (%lambda tknz (s)
856
                                                        (let ((ch (s 'peek-char)))
857
                                                          (%if (%eq? ch 'eos)
858
                                                               %nil
859
                                                               (%if (whitespace? ch)
860
                                                                    %nil
861
                                                                    (%if (isalpha? ch)
862
                                                                         (%progn
863
                                                                          (%set! 'type 'symbol)
864
                                                                          (%cons (s 'get-char)
865
                                                                                 (tknz s)))
866
                                                                         (%if (member ch digits %char-eq?)
867
                                                                              (%cons (s 'get-char)
868
                                                                                     (tknz s))
869
                                                                              %nil)))))))
870
                                      ((%lambda snoc (a b)
871
                                                (%cons b a))
872
                                       (let ((lst (%cons ch (tknz s))))
873
                                         ((%if (%eq? type 'integer)
874
                                               parse-integer
875
                                               list->string)
876
                                          lst))
877
                                       type)))))
878
 
879
   ;; Tokenize a string
880
   (%define 'tokenize-string-rec (%lambda tokenize-string-rec (s)
881
                                          (let ((ch (s 'get-char)))
882
                                            (%if (%char-eq? ch #\") ; XXX: Check for end of stream
883
                                                 %nil
884
 
885
                                                 (%cons ch (tokenize-string-rec s))))))
886
 
887
   (%define 'tokenize-string (%lambda tokenize-string (s)
888
                                      (let ((sl (tokenize-string-rec s)))
889
                                        (%cons 'string (list->string sl)))))
890
 
891
   ;; Tokenize a hash object
892
   (%define 'tokenize-hash-x (%lambda tokenize-hash-x (s)
893
                                      (%progn
894
                                       (%define 'rec (%lambda tokenize-hash-x-rec ()
895
                                                              (let ((ch (s 'peek-char)))
896
                                                                (%if (member ch digits-hex %char-eq?)
897
                                                                     (%cons (s 'get-char) (rec))
898
                                                                     %nil))))
899
                                       (parse-integer* (rec) 0 16))))
900
 
901
 
902
   (%define 'tokenize-hash (%lambda tokenize-hash (s)
903
                                    (let ((ch (s 'get-char)))
904
                                      (%if (%char-eq? ch #\\)
905
                                           (%cons 'character (s 'get-char))
906
                                           (%if (%char-eq? ch #\x)
907
                                                (%cons 'integer (tokenize-hash-x s))
908
                                                (%cons 'error "Unknown hash character"))))))
909
 
910
   ;; Tokenize a stream
911
   (%define 'tokenize (%lambda tokenize (s)
912
                               (%progn
913
                                (skip-whitespace s)
914
                                (let ((ch (s 'get-char)))
915
                                  (%if (%eq? ch 'eos)
916
                                       (%cons 'eos %nil)
917
                                       (%if (%char-eq? ch #\()
918
                                            (%cons 'lparen %nil)
919
                                            (%if (%char-eq? ch #\))
920
                                                 (%cons 'rparen %nil)
921
                                                 (%if (%char-eq? ch #\')
922
                                                      (%cons 'quote %nil)
923
                                                      (%if (%char-eq? ch #\")
924
                                                           (tokenize-string s)
925
                                                           (%if (%char-eq? ch #\#)
926
                                                                (tokenize-hash s)
927
                                                                (tokenize-sym s ch)))))))))))
928
 
929
   ;; Make a token stream
930
   (%define 'make-token-stream (%lambda make-token-stream (s)
931
                                        (let ((tok %nil))
932
                                          (%lambda token-stream (cmd)
933
                                                   (%if (%eq? cmd 'next)
934
                                                        (%if tok
935
                                                             (let ((tok2 tok))
936
                                                               (%set! 'tok %nil)
937
                                                               tok2)
938
                                                             (tokenize s))
939
                                                        (%if (%eq? cmd 'peek)
940
                                                             (%if tok
941
                                                                  tok
942
                                                                  (%progn
943
                                                                   (%set! 'tok (tokenize s))
944
                                                                   tok))
945
                                                             %nil))))))
946
 
947
   ;; Parse a list from a token stream
948
   (%define 'parse-list (%lambda parse-list (s)
949
                                 (let ((tok (s 'peek)))
950
                                   (let ((token (%car tok)))
951
                                     (%if (%eq? token 'eos)
952
                                          (%error "Parse error, missing rparen at end of stream")
953
                                          (%if (%eq? token 'rparen)
954
                                               (%progn
955
                                                (s 'next)
956
                                                %nil)
957
                                               (%cons (parse s) (parse-list s))))))))
958
 
959
   ;; Check if the string is a T type
960
   (%define 'is-t? (%lambda is-t? (str)
961
                            (%if (%num-eq? (%array-size str) 1)
962
                                 (%if (%char-eq? (%array-get str 0) #\T)
963
                                      %t
964
                                      %nil)
965
                                 %nil)))
966
 
967
   ;; Check if the string s a NIL type
968
   (%define 'is-nil? (%lambda is-nil? (str)
969
                              (string=? str "NIL")))
970
 
971
   ;; Uppercase a string
972
   (%define 'string-upper-rec (%lambda string-upper-rec (orig str i)
973
                                       (%if (%num-eq? i (%array-size orig))
974
                                            str
975
                                            (%progn
976
                                             (%array-set str i (char-upper (%array-get orig i)))
977
                                             (string-upper-rec orig str (1+ i))))))
978
 
979
   (%define 'string-upper (%lambda string-upper (str)
980
                                   (let ((str2 (%make-array (%array-size str) #\a)))
981
                                     (string-upper-rec str str2 0))))
982
 
983
   ;; Make a symbol of a string
984
   ;; T and NIL are "special" symbols
985
   (%define 'symbolify (%lambda symbolify (sym)
986
                                (%if (%num-eq? (%array-size sym) 1)
987
                                     (%if (is-t? sym)
988
                                          %t
989
                                          (%if (%char-eq? #\. (%array-get sym 0))
990
                                               '%.
991
                                               (intern sym)))
992
                                     (%if (is-nil? sym)
993
                                          %nil
994
                                          (intern sym)))))
995
   ;; Parse a token stream
996
   (%define 'parse (%lambda parse (s)
997
                            (let ((tok (s 'next)))
998
                              (%if (%eq? (%car tok) 'lparen)
999
                                   (parse-list s)
1000
                                   (%if (or3 (%eq? (%car tok) 'integer) (%eq? (%car tok) 'string) (%eq? (%car tok) 'character))
1001
                                        (%cdr tok)
1002
                                        (%if (%eq? (%car tok) 'symbol)
1003
                                             (symbolify (string-upper (%cdr tok)))
1004
                                             (%if (%eq? (%car tok) 'quote)
1005
                                                  (%cons '%quote (%cons (parse s) %nil)))))))))
1006
 
1007
   ;; Parse a string into cons cells
1008
   (%define 'read-from-string (%lambda read-from-string (str)
1009
                                       (let ((s (make-token-stream (make-string-stream str 0))))
1010
                                         (parse s))))
1011
 
1012
   ;; Write each character in the list to current output
1013
   (%define 'print-list* (%lambda print-list* (list)
1014
                                  (%if list
1015
                                       (%progn
1016
                                        (%put-char current-output (%car list))
1017
                                        (print-list* (%cdr list)))
1018
                                       %nil)))
1019
 
1020
   ;; Print a character
1021
   (%define 'print-char (%lambda print-char (ch)
1022
                                 (print-list* (%%list #\# #\\ ch))))
1023
 
1024
 
1025
   ;; Check if an array is a string
1026
   (%define 'is-string?-rec (%lambda is-string?-rec (arr i)
1027
                                     (%if (%num-eq? i (%array-size arr))
1028
                                          %t
1029
                                          (%if (%num-eq? (%type (%array-get arr i)) +type-char+)
1030
                                               (is-string?-rec arr (1+ i))
1031
                                               %nil))))
1032
 
1033
   (%define 'is-string? (%lambda is-string? (arr)
1034
                                 (is-string?-rec arr 0)))
1035
 
1036
   ;; Print a string
1037
   (%define 'print-string-rec (%lambda print-string-rec (arr i)
1038
                                       (%if (%num-eq? (%array-size arr) i)
1039
                                            %nil
1040
                                            (%progn
1041
                                             (%put-char current-output (%array-get arr i))
1042
                                             (print-string-rec arr (1+ i))))))
1043
 
1044
   (%define 'print-string (%lambda print-string (arr)
1045
                                   (%progn
1046
                                    (%put-char current-output #\")
1047
                                    (print-string-rec arr 0)
1048
                                    (%put-char current-output #\"))))
1049
 
1050
   ;; Print an array
1051
   (%define 'print-array-rec (%lambda print-array-rec (arr i)
1052
                                      (%if (%num-eq? (%array-size arr) i)
1053
                                           %nil
1054
                                           (%progn
1055
                                            (print (%array-get arr i))
1056
                                            (%put-char current-output #\Space)
1057
                                            (print-array-rec arr (1+ i))))))
1058
 
1059
 
1060
   (%define 'print-array (%lambda print-array (arr)
1061
                                        ; String is a special type of array
1062
                                  (%if (is-string? arr)
1063
                                       (print-string arr)
1064
                                       (%progn
1065
                                        (print-list* (%%list #\# #\[))
1066
                                        (%put-char current-output #\Space)
1067
                                        (print-array-rec arr 0)
1068
                                        (%put-char current-output #\])))))
1069
 
1070
   ;; See if a cons cell really is a list
1071
   (%define 'is-list? (%lambda is-list? (cons)
1072
                               (%if (%num-eq? (%type cons) +type-cons+)
1073
                                    (is-list? (%cdr cons))
1074
                                    (%if (%num-eq? (%type cons) +type-nil+)
1075
                                         %t
1076
                                         %nil))))
1077
   ;; Print a list
1078
   (%define 'print-list-rec (%lambda print-list-rec (list)
1079
                                     (%progn
1080
                                      (print (%car list))
1081
                                      (%if (%num-eq? (%type (%cdr list)) +type-nil+)
1082
                                           %nil
1083
                                           (%progn
1084
                                            (%put-char current-output #\Space)
1085
                                            (print-list-rec (%cdr list)))))))
1086
 
1087
   (%define 'print-list (%lambda print-list (list)
1088
                                 (%progn
1089
                                  (%put-char current-output #\()
1090
                                  (print-list-rec list)
1091
                                  (%put-char current-output #\)))))
1092
 
1093
   ;; Print a cons cell
1094
   (%define 'print-cons (%lambda print-cons (cons)
1095
                                 (%if (is-list? cons)
1096
                                      (print-list cons)
1097
                                      (%progn
1098
                                       (%put-char current-output #\()
1099
                                       (print (%car cons))
1100
                                       (%put-char current-output #\Space)
1101
                                       (%put-char current-output #\.)
1102
                                       (%put-char current-output #\Space)
1103
                                       (print (%cdr cons))
1104
                                       (%put-char current-output #\))))))
1105
 
1106
   ;; Print an integer
1107
   (%define 'print-integer-rec (%lambda print-integer-rec (int list)
1108
                                        (%if (%num-eq? int 0)
1109
                                             list
1110
                                             (print-integer-rec (%if (%num-eq? *print-base* 10)
1111
                                                                     (%div int 10)
1112
                                                                     (%bitwise-shift int -4))
1113
                                                                (%cons
1114
                                                                 (%if (%num-eq? *print-base* 10)
1115
                                                                      (%mod int 10)
1116
                                                                      (%bitwise-and int #xF))
1117
                                                                 list)))))
1118
 
1119
                                        ; XXX: Make it an array for direct lookup?
1120
   ;; Integer to digit character mapping
1121
   (%define 'digit->char-map (%%list (%cons 0 #\0)
1122
                                     (%cons 1 #\1)
1123
                                     (%cons 2 #\2)
1124
                                     (%cons 3 #\3)
1125
                                     (%cons 4 #\4)
1126
                                     (%cons 5 #\5)
1127
                                     (%cons 6 #\6)
1128
                                     (%cons 7 #\7)
1129
                                     (%cons 8 #\8)
1130
                                     (%cons 9 #\9)
1131
                                     (%cons 10 #\A)
1132
                                     (%cons 11 #\B)
1133
                                     (%cons 12 #\C)
1134
                                     (%cons 13 #\D)
1135
                                     (%cons 14 #\E)
1136
                                     (%cons 15 #\F)
1137
                                     (%cons 10 #\a)
1138
                                     (%cons 11 #\b)
1139
                                     (%cons 12 #\c)
1140
                                     (%cons 13 #\d)
1141
                                     (%cons 14 #\e)
1142
                                     (%cons 15 #\f)))
1143
   ;; Convert an integer (0 >= n < 10)
1144
   (%define 'digit->char-rec (%lambda digit->char-rec (int list)
1145
                                      (%if list
1146
                                           (%if (%num-eq? (%car (%car list)) int)
1147
                                                (%cdr (%car list))
1148
                                                (digit->char-rec int (%cdr list)))
1149
                                           #\?)))
1150
   (%define 'digit->char (%lambda digit->char (int)
1151
                                  (digit->char-rec int digit->char-map)))
1152
 
1153
   ;; Convert a character to a digit [0, F]
1154
   (%define 'char->digit-rec (%lambda digit->char-rec (ch list)
1155
                                      (%if list
1156
                                           (%if (%char-eq? (%cdr (%car list)) ch)
1157
                                                (%car (%car list))
1158
                                                (char->digit-rec ch (%cdr list)))
1159
                                           0)))
1160
   (%define 'char->digit (%lambda digit->char (ch)
1161
                                  (char->digit-rec ch digit->char-map)))
1162
 
1163
   (%define 'print-integer (%lambda print-integer (int)
1164
                                    (%if (%num-eq? int 0)
1165
                                         (print-list* (%if (%num-eq? *print-base* 10)
1166
                                                           (%%list #\0)
1167
                                                           (%%list #\# #\x #\0)))
1168
                                         (print-list*
1169
                                          (let ((start-int (%if (%num-eq? *print-base* 10)
1170
                                                                %nil
1171
                                                                (%%list #\# #\x))))
1172
                                            (print-list* start-int)
1173
                                            (%if (%less-than? int 0)
1174
                                                 (%cons #\- (map digit->char (print-integer-rec (%mul (%sub 0 1) int) %nil)))
1175
                                                 (map digit->char (print-integer-rec int %nil))))))))
1176
 
1177
 
1178
   ;; Print a function
1179
   (%define
1180
    'print-function
1181
    (%lambda
1182
     print-function (f)
1183
     (%progn
1184
      (%put-char current-output #\#)
1185
      (%put-char current-output #\()
1186
      (print (function-name f))
1187
      (%put-char current-output #\)))))
1188
 
1189
   ;; Print a builtin function
1190
   (%define
1191
    'print-builtin
1192
    (%lambda
1193
     print-builtin (b)
1194
     (%progn
1195
      (%put-char current-output #\#)
1196
      (%put-char current-output #\()
1197
      (print (%builtin-name b))
1198
      (%put-char current-output #\)))))
1199
 
1200
 
1201
   ;; Print an object
1202
   (%define
1203
    'print
1204
    (%lambda
1205
     print (expr)
1206
     (%if (%num-eq? (%type expr) +type-t+)
1207
          (%put-char current-output #\T)
1208
          (%if (%num-eq? (%type expr) +type-nil+)
1209
               (print-list* (%%list #\N #\I #\L))
1210
               (%if (%num-eq? (%type expr) +type-char+)
1211
                    (print-char expr)
1212
                    (%if (%num-eq? (%type expr) +type-array+)
1213
                         (print-array expr)
1214
                         (%if (%num-eq? (%type expr) +type-cons+)
1215
                              (print-cons expr)
1216
                              (%if (%num-eq? (%type expr) +type-symbol+)
1217
                                   (print-string-rec (%symbol-to-string expr) 0)
1218
                                   (%if (%num-eq? (%type expr) +type-int+)
1219
                                        (print-integer expr)
1220
                                        (%if (%num-eq? (%type expr) +type-function+)
1221
                                             (print-function expr)
1222
                                             (%if (%num-eq? (%type expr) +type-builtin+)
1223
                                                  (print-builtin expr)
1224
                                                  (%put-char current-output #\#))))))))))))
1225
 
1226
   ;; Write newline
1227
   (%define 'newline (%lambda newline ()
1228
                              (%progn
1229
                               (%put-char current-output #\Newline)
1230
                               (%put-char current-output #\Return)
1231
                               nil)))
1232
 
1233
 
1234
   ;; Parse the input from a device
1235
   (%define 'read-from-device (%lambda read-from-device (input-device)
1236
                                       (let ((s (make-token-stream (make-device-input-stream input-device))))
1237
                                         (parse s))))
1238
 
1239
   ;; Read line
1240
   (%define 'read-line
1241
            (%lambda read-line (input-device)
1242
                     (let ((s (make-device-input-stream input-device)))
1243
                       (%define 'rec (%lambda read-line-rec ()
1244
                                              (let ((ch (s 'get-char)))
1245
                                                (%if (or2 (%char-eq? #\Newline ch) (%char-eq? #\Return ch))
1246
                                                     %nil
1247
                                                     (%cons ch (rec))))))
1248
                       (skip-whitespace s)
1249
                       (list->string (rec)))))
1250
 
1251
   ;; Remove backspaced characters
1252
   (%define 'fix-backspace
1253
            (%lambda fix-backspace (strin)
1254
                     (let ((str (%make-array (%array-size strin) #\Newline)))
1255
                       (let ((size (%array-size strin)))
1256
                         (%define 'rec
1257
                                  (%lambda fix-backspace-rec (i j)
1258
                                           (%if (%num-eq? j size)
1259
                                                (%if (%less-than? i j)
1260
                                                     (%progn
1261
                                                      (%array-set str i #\Newline)
1262
                                                      (rec (1+ i) j))
1263
                                                     str)
1264
                                                (%if (%char-eq? (%array-get strin j) #\Backspace)
1265
                                                     (rec (%if (%num-eq? i 0) 0 (1- i)) (1+ j))
1266
                                                     (%progn
1267
                                                      (%array-set str i (%array-get strin j))
1268
                                                      (rec (1+ i) (1+ j)))))))
1269
                         (rec 0 0)))))
1270
 
1271
 
1272
 
1273
 
1274
   ;; Macro system
1275
   ;; Move to nth-lisp file, RSN
1276
 
1277
   (%define 'macro-functions %nil)
1278
 
1279
   ;; defmacro
1280
   (%define 'defmacro-fn (%lambda %defmacro (name fn)
1281
                                  (%set! 'macro-functions
1282
                                         (%cons (%cons name fn)
1283
                                                macro-functions))))
1284
 
1285
   (%define 'get-macro-fn (%lambda get-macro-fn (name)
1286
                                   (%progn
1287
                                    (%define 'rec
1288
                                             (%lambda get-macro-fn-rec (name list)
1289
                                                      (%if list
1290
                                                           (%if (%eq? (%car (%car list)) name)
1291
                                                                (%cdr (%car list))
1292
                                                                (rec name (%cdr list)))
1293
                                                           %nil)))
1294
                                    (rec name macro-functions))))
1295
 
1296
 
1297
   ;; Tree walker and expander
1298
 
1299
   (%define 'fix-lambda-arguments
1300
            (%lambda fix-lambda-arguments (args)
1301
                     (%progn
1302
                      (%define 'rec (%lambda fix-lambda-arguments-rec (args)
1303
                                             (%if args
1304
                                                  (%if (%eq? '%. (%car args))
1305
                                                       (%car (%cdr args))
1306
                                                       (%cons (%car args) (rec (%cdr args))))
1307
                                                  %nil)))
1308
                      (%if (%num-eq? (%type args) +type-cons+)
1309
                           (rec args)
1310
                           args))))
1311
 
1312
   (%define 'fix-pair
1313
            (%lambda fix-pair (pair)
1314
                     (%if (is-list? pair)
1315
                          (%if (%num-eq? (length pair) 3)
1316
                               (%if (%eq? '%. (%car (%cdr pair)))
1317
                                    (%%list (%car pair) (%car (%cdr (%cdr pair))))
1318
                                    pair)
1319
                               pair)
1320
                          pair)))
1321
 
1322
   (%define 'expand-macro
1323
            (%lambda expand-macro (root)
1324
                     (%if (%num-eq? (%type root) +type-cons+)
1325
                          (let ((mfn (get-macro-fn (%car root))))
1326
                            (%if mfn
1327
                                 (expand-macro (mfn root))
1328
                                 root))
1329
                          root)))
1330
 
1331
   (%define 'tree-walker
1332
            (%lambda tree-walker (root)
1333
                     (%if (%num-eq? (%type root) +type-cons+)
1334
                          (%if (%eq? (%car root) '%quote)
1335
                               root
1336
                               (let ((root (expand-macro (fix-pair root))))
1337
                                 (%if (%num-eq? (%type root) +type-cons+)
1338
                                      (%if (%eq? (%car root) '%lambda)
1339
                                           (%cons '%lambda
1340
                                                  (%cons (%car (%cdr root))
1341
                                                         (%cons (fix-lambda-arguments (%car (%cdr (%cdr root))))
1342
                                                                (map tree-walker (%cdr (%cdr (%cdr root)))))))
1343
                                           (map tree-walker root))
1344
                                      root)))
1345
                          root)))
1346
 
1347
;;; Move this to NTH-Lisp code base
1348
;;; !!!
1349
 
1350
   ;; Lambda macro
1351
   (defmacro-fn 'lambda
1352
       (%lambda 'lambda-macro (root)
1353
                (list '%lambda
1354
                      'anonymous
1355
                      (%car (%cdr root))
1356
                      (%cons '%progn
1357
                             (%cdr (%cdr root))))))
1358
 
1359
   (defmacro-fn 'named-lambda
1360
       (%lambda 'named-lambda-macro (root)
1361
                (list '%lambda
1362
                      (%car (%cdr root))
1363
                      (%car (%cdr (%cdr root)))
1364
                      (%cons '%progn
1365
                             (%cdr (%cdr (%cdr root)))))))
1366
 
1367
 
1368
   (defmacro-fn 'progn
1369
       (%lambda 'progn-macro (root)
1370
                (%cons '%progn
1371
                       (%cdr root))))
1372
 
1373
   (defmacro-fn 'quote
1374
       (%lambda 'quote-macro (root)
1375
                (%cons '%quote
1376
                       (%cdr root))))
1377
 
1378
   (defmacro-fn 'let
1379
       (%lambda 'let-macro (root)
1380
                (list (%cons 'named-lambda
1381
                             (%cons 'let
1382
                                    (%cons (list (%car (%car (%car (%cdr root)))))
1383
                                           (%cdr (%cdr root)))))
1384
                      (%car (%cdr (%car (%car (%cdr root))))))))
1385
 
1386
   (defmacro-fn 'define
1387
       (%lambda 'define-macro (root)
1388
                (list '%define
1389
                      (list '%quote (%car (%cdr root)))
1390
                      (%car (%cdr (%cdr root))))))
1391
   (defmacro-fn 'setq!
1392
       (%lambda 'setq!-macro (root)
1393
                (list '%set!
1394
                      (list '%quote (%car (%cdr root)))
1395
                      (%car (%cdr (%cdr root))))))
1396
 
1397
   (defmacro-fn 'cond
1398
       (%lambda 'cond-macro (root)
1399
                (%progn
1400
                 (%define 'rec (%lambda 'cond-macro-rec (lst)
1401
                                        (%if lst
1402
                                             (let ((pair (%car lst)))
1403
                                               (list '%if
1404
                                                     (%car pair)
1405
                                                     (%car (%cdr pair))
1406
                                                     (rec (%cdr lst))))
1407
                                             %nil)))
1408
                 (rec (%cdr root)))))
1409
 
1410
   (defmacro-fn 'if
1411
       (%lambda 'if-macro (root)
1412
                (list '%if
1413
                      (%car (%cdr root))
1414
                      (%car (%cdr (%cdr root)))
1415
                      (%if (%num-eq? (length (%cdr root)) 2)
1416
                           %nil
1417
                           (%car (%cdr (%cdr (%cdr root))))))))
1418
 
1419
   (defmacro-fn 'or
1420
       (%lambda 'or-macro (root)
1421
                (%progn
1422
                 (%define 'rec (%lambda or-macro-rec (args)
1423
                                        (%if args
1424
                                             (list (list '%lambda 'anonymous (list 'x)
1425
                                                         (list '%if
1426
                                                               'x 'x
1427
                                                               (rec (%cdr args))))
1428
                                                   (%car args))
1429
                                             %nil)))
1430
                 (rec (%cdr root)))))
1431
 
1432
   (defmacro-fn 'and
1433
       (%lambda 'and-macro (root)
1434
                (%progn
1435
                 (%define 'rec (%lambda and-macro-rec (args)
1436
                                        (%if args
1437
                                             (list '%if
1438
                                                   (%car args)
1439
                                                   (rec (%cdr args))
1440
                                                   (%car args))
1441
                                             %t)))
1442
                 (rec (%cdr root)))))
1443
 
1444
   ;; Reduce
1445
   (%define 'reduce (%lambda 'reduce (fn init list)
1446
                             (%if list
1447
                                  (reduce fn (fn init (%car list)) (%cdr list))
1448
                                  init)))
1449
 
1450
   ;; Make a function that calls reduce with the first argument as the
1451
   ;; init value and the rest of the arguments as the list.
1452
   ;; reducer takes a function that will be used during the reduce  as
1453
   ;; the only input.
1454
   (%define 'reducer (%lambda 'reduce (fn identity)
1455
                              (%lambda 'anonymous-reducer list
1456
                                       (%if list
1457
                                            (reduce fn (%if identity identity (%car list)) (%if identity list (%cdr list)))
1458
                                            identity))))
1459
 
1460
   (%define '+ (reducer %add 0))
1461
   (%define '- (%lambda sub lst
1462
                        (%if (%num-eq? (length lst) 1)
1463
                             (%sub 0 (%car lst))
1464
                             (reduce %sub (%car lst) (%cdr lst)))))
1465
   (%define '* (reducer %mul 1))
1466
   (%define '/ %div)
1467
   (%define 'mod %mod)
1468
 
1469
   (%define '= %num-eq?)
1470
   (%define '< %less-than?)
1471
   (%define '> (%lambda 'greater-than? (a b)
1472
                        (%if (or2 (%num-eq? a b)
1473
                                  (%less-than? a b))
1474
                             %nil
1475
                             %t)))
1476
 
1477
   (%define 'car %car)
1478
   (%define 'cdr %cdr)
1479
   (%define 'cons %cons)
1480
   (%define 'set! %set!)
1481
   (%define 'set-car! %set-car!)
1482
   (%define 'set-cdr! %set-cdr!)
1483
   (%define 'make-array %make-array)
1484
   (%define 'array-get %array-get)
1485
   (%define 'array-size %array-size)
1486
 
1487
   (defun append (li lu)
1488
     (%if li
1489
         (cons (car li) (append (cdr li) lu))
1490
         lu))
1491
 
1492
   (defun null? (dings)
1493
     (%if (%eq? nil dings)
1494
         %t
1495
         %nil))
1496
 
1497
 
1498
 
1499
;;; !!! END
1500
 
1501
   (%define
1502
    'combine
1503
    (%lambda
1504
     combine (f g)           ; produces combination of single-argument
1505
                                        ; functions f and g
1506
     (%lambda combination (x) (f (g x)))))
1507
 
1508
   (%define 'caar (combine car car))
1509
   (%define 'cadr (combine car cdr))
1510
   (%define 'cdar (combine cdr car))
1511
   (%define 'cddr (combine cdr cdr))
1512
   (%define 'cdddr (combine cddr cdr))
1513
   (%define 'caddr (combine cadr cdr))
1514
   (%define 'cadddr (combine caddr cdr))
1515
 
1516
   (%define 'igorev-state-func-frame car)
1517
   (%define 'igorev-state-condition cadr)
1518
   (%define 'igorev-state-iterations caddr)
1519
 
1520
   (%define 'igorev-func-frame-func car)
1521
   (%define 'igorev-func-frame-env cadr)
1522
   (%define 'igorev-func-frame-eval-frame caddr)
1523
   (%define 'igorev-func-frame-parent cadddr)
1524
 
1525
   (%define 'igorev-eval-frame-expr car)
1526
   (%define 'igorev-eval-frame-arg cadr)
1527
   (%define 'igorev-eval-frame-result caddr)
1528
   (%define 'igorev-eval-frame-phase cadddr)
1529
   (%define 'igorev-eval-frame-parent (combine caddr cddr))
1530
 
1531
   (%define
1532
    'igorev-state-huge-success?
1533
    (%lambda
1534
     igorev-state-huge-success? (state)
1535
     (%eq? (igorev-state-condition state) nil)))
1536
 
1537
   (%define
1538
    'igorev-state-result
1539
    (%lambda
1540
     igorev-state-result (state)
1541
     (igorev-eval-frame-result
1542
      (igorev-func-frame-eval-frame
1543
       (igorev-state-func-frame state)))))
1544
 
1545
   (%define
1546
    'igorev-state-expr
1547
    (%lambda
1548
     igorev-state-expr (state)
1549
     (igorev-eval-frame-expr
1550
      (igorev-func-frame-eval-frame
1551
       (igorev-state-func-frame state)))))
1552
 
1553
   (%define 'igorev-env-local-bindings car)
1554
 
1555
 
1556
   (%define
1557
    'function-name
1558
    (%lambda
1559
     function-name (f)
1560
     (%car (%function-data f))))
1561
 
1562
   (%define
1563
    'function-param-list
1564
    (%lambda
1565
     function-param-list (f)
1566
     (%cadr (%function-data f))))
1567
 
1568
   (%define
1569
    'function-expr
1570
    (%lambda
1571
     function-expr (f)
1572
     (%caddr (%function-data f))))
1573
 
1574
   (%define
1575
    'function-env
1576
    (%lambda
1577
     function-end (f)
1578
     (%cadddr (%function-data f))))
1579
 
1580
 
1581
 
1582
   (%define
1583
    'show-error-message
1584
    (%lambda
1585
     show-error-message (state)
1586
     (%progn
1587
      (display "Error: ")
1588
      (print (igorev-state-condition state))
1589
      (display " at ")
1590
      (print (igorev-state-expr state))
1591
      (newline)
1592
      (display " in ")
1593
      (print (igorev-func-frame-func (igorev-state-func-frame state)))
1594
      (newline))))
1595
 
1596
 
1597
   (%define
1598
    'display
1599
    (%lambda
1600
     display (str)
1601
     (%progn
1602
      (%define
1603
       'display-rec
1604
       (%lambda
1605
        display-rec (i)
1606
        (%if (%less-than? i (%array-size str))
1607
             (%progn
1608
              (%put-char current-output (%array-get str i))
1609
              (display-rec (1+ i)))
1610
             nil)))
1611
      (%if (is-string? str)
1612
           (display-rec 0)
1613
           (%error (list '%err-type-error str 'string))))))
1614
 
1615
   (defun displine (str)
1616
     (display str)
1617
     (newline)
1618
     nil)
1619
 
1620
 
1621
 
1622
;;    (%define
1623
;;     'new-environment
1624
;;     (%lambda
1625
;;      new-environment (parent)
1626
;;      (%cons %nil parent)))
1627
 
1628
   (defun new-environment (parent)
1629
     (%cons %nil parent))
1630
 
1631
   (defun debug (state)
1632
     (displine "Entering debugger")
1633
     (let ((top-fframe (igorev-state-func-frame state)))
1634
       (let ((top-eframe (igorev-func-frame-eval-frame top-fframe)))
1635
         (dbg-show-fframe top-fframe)
1636
         (dbg-show-eframe top-eframe)
1637
         (dbg-repl state top-fframe '() top-eframe '()))))
1638
 
1639
   (defun dbg-show-fframe (f)
1640
     (displine "Current function frame:")
1641
     (display " Function: ")
1642
     (print (igorev-func-frame-func f))
1643
     (newline)
1644
     (display " Local bindings: ")
1645
     (print (igorev-env-local-bindings
1646
             (igorev-func-frame-env f)))
1647
     (newline))
1648
 
1649
   (defun dbg-show-eframe (e)
1650
     (displine "Current eval frame:")
1651
     (display " Expr: ")
1652
     (print (igorev-eval-frame-expr e))
1653
     (newline)
1654
     (display " Arg: ")
1655
     (print (igorev-eval-frame-arg e))
1656
     (newline)
1657
     (display " Result: ")
1658
     (print (igorev-eval-frame-result e))
1659
     (newline)
1660
     (display " Phase: ")
1661
     (print (igorev-eval-frame-phase e))
1662
     (newline))
1663
 
1664
   (defun dbg-show-fstack (frame descendants)
1665
     (defun print-frame (f num is-current)
1666
       (%if is-current (display "(*)") nil)
1667
       (print num)
1668
       (display ": ")
1669
       (print (igorev-func-frame-func f))
1670
       (newline))
1671
     (defun print-frames (frames i)
1672
       (%if frames
1673
            (%progn
1674
             (print-frame (car frames) i
1675
                          (%eq? (car frames) frame))
1676
             (print-frames (cdr frames) (1+ i)))
1677
            nil))
1678
     (defun collect-frames (frame rest)
1679
       (%if frame
1680
            (collect-frames (igorev-func-frame-parent frame)
1681
                            (cons frame rest))
1682
            rest))
1683
     (print-frames (collect-frames frame descendants) 0))
1684
 
1685
   (defun dbg-show-estack (frame descendants)
1686
     (defun print-frame (f num is-current)
1687
       (%if is-current (display "(*)") nil)
1688
       (print num)
1689
       (display ": ")
1690
       (print (igorev-eval-frame-expr f))
1691
       (newline))
1692
     (defun print-frames (frames i)
1693
       (%if frames
1694
            (%progn
1695
             (print-frame (car frames) i
1696
                          (%eq? (car frames) frame))
1697
             (print-frames (cdr frames) (1+ i)))
1698
            nil))
1699
     (defun collect-frames (frame rest)
1700
       (%if frame
1701
            (collect-frames (igorev-eval-frame-parent frame)
1702
                            (cons frame rest))
1703
            rest))
1704
     (print-frames (collect-frames frame descendants) 0))
1705
 
1706
   (defun dbg-show-env (fframe)
1707
     (displine "(TODO)"))
1708
 
1709
   (defun dbg-repl (state fframe fframes-below eframe eframes-below)
1710
     (%define 'continue %t)
1711
     (defun env ()
1712
       (igorev-func-frame-env fframe))
1713
     (defun deval (expr)
1714
       (%eval expr (env)))
1715
     (defun up ()
1716
       (let ((parent (igorev-func-frame-parent fframe)))
1717
         (%if parent
1718
              (%progn
1719
               (%set! 'fframes-below (cons fframe fframes-below))
1720
               (%set! 'fframe parent)
1721
               (%set! 'eframe (igorev-func-frame-eval-frame fframe))
1722
               (%set! 'eframes-below '())
1723
               (displine "Moved one function frame up"))
1724
              (displine "Current function frame is an orphan"))))
1725
     (defun down ()
1726
       (%if fframes-below
1727
            (%progn
1728
             (%set! 'fframe (car fframes-below))
1729
             (%set! 'fframes-below (cdr fframes-below))
1730
             (%set! 'eframe (igorev-func-frame-eval-frame fframe))
1731
             (%set! 'eframes-below '())
1732
             (displine "Moved one function frame down"))
1733
            (displine "Current function frame is childless")))
1734
     (defun eup ()
1735
       (let ((parent (igorev-eval-frame-parent eframe)))
1736
         (%if parent
1737
              (%progn
1738
               (%set! 'eframes-below (cons eframe eframes-below))
1739
               (%set! 'eframe parent)
1740
               (displine "Moved one eval frame up"))
1741
              (displine "Current eval frame is an orphan"))))
1742
     (defun edown ()
1743
       (%if eframes-below
1744
            (%progn
1745
             (%set! 'eframe (car eframes-below))
1746
             (%set! 'eframes-below (cdr eframes-below))
1747
             (displine "Moved one eval frame down"))
1748
            (displine "Current eval frame is childless")))
1749
     (defun show (what)
1750
       (%if (%eq? what 'fframe)
1751
            (dbg-show-fframe fframe)
1752
            (%if (%eq? what 'eframe)
1753
                 (dbg-show-eframe eframe)
1754
                 (%if (%eq? what 'env)
1755
                      (dbg-show-env fframe)
1756
                      (%if (%eq? what 'fstack)
1757
                           (dbg-show-fstack fframe fframes-below)
1758
                           (%if (%eq? what 'estack)
1759
                                (dbg-show-estack eframe eframes-below)
1760
                                (displine "What what?")))))))
1761
     (defun quit ()
1762
       (%set! 'continue %nil))
1763
     (defun read ()
1764
       (display "dbg> ")
1765
       (let ((expr (tree-walker
1766
                    (read-from-string (fix-backspace (read-line current-input))))))
1767
         (newline)
1768
         expr))
1769
     (defun eval/print (expr)
1770
       (let ((state (%eval-partial
1771
                     (%make-eval-state expr
1772
                                       (new-environment (%current-environment)))
1773
                     0)))
1774
         (%if (igorev-state-huge-success? state)
1775
              (%progn
1776
               (display "Result: ")
1777
               (print (igorev-state-result state))
1778
               (newline))
1779
              (show-error-message state))))
1780
 
1781
     (eval/print (read))
1782
     (%if continue
1783
          (dbg-repl state fframe fframes-below eframe eframes-below)
1784
          (displine "Exiting debugger")))
1785
 
1786
 
1787
 
1788
   (defun try (expr)
1789
     (let ((state (%eval-partial
1790
                   (%make-eval-state (tree-walker expr)
1791
                                     (%current-environment))
1792
                   0)))
1793
       (%if (igorev-state-huge-success? state)
1794
            (list 'success (igorev-state-result state))
1795
            (list 'interrupt (cdr (igorev-state-condition state)) state))))
1796
 
1797
   (defun catch-fn (handlers expr)
1798
     (defun find-handler (condition handlers)
1799
       (%if handlers
1800
            (%if ((caar handlers) condition)
1801
                 (cdar handlers)
1802
                 (find-handler condition (cdr handlers)))
1803
            nil))
1804
     (let ((result (try expr)))
1805
       (%if (%eq? (car result) 'success)
1806
            (cadr result)
1807
            (let ((condition (cadr result)))
1808
              (let ((handler (find-handler condition handlers)))
1809
                (%if handler
1810
                     (handler condition)
1811
                     (%error condition)))))))
1812
 
1813
   (defmacro-fn
1814
       'catch
1815
       (%lambda
1816
        catch-macro (root)
1817
        (let ((cond-var (cadr root)))
1818
          (let ((handlers (caddr root)))
1819
            (let ((body (cdddr root)))
1820
              (list 'catch-fn
1821
                    (cons
1822
                     'list
1823
                     (map (%lambda
1824
                           catch-macro-create-handler-function (handler)
1825
                           (list 'cons
1826
                                 (list '%lambda 'catch-handler-predicate (list cond-var)
1827
                                       (car handler))
1828
                                 (list '%lambda 'catch-handler-function (list cond-var)
1829
                                       (cadr handler))))
1830
                          handlers))
1831
                    (list '%quote (cons '%progn body))))))))
1832
 
1833
   (defun condition-type (condition)
1834
     (%if (is-list? condition)
1835
          (car condition)
1836
          condition))
1837
 
1838
 
1839
 
1840
   (%define '*igorrepl-continue* %t)
1841
   (%define
1842
    'quit
1843
    (%lambda
1844
     quit ()                            ; make it all go away
1845
     (%set! '*igorrepl-continue* nil)))
1846
 
1847
   ;; REPL
1848
   (%define 'igorrepl (%lambda igorrepl (n env)
1849
                               (%progn
1850
                                (display "IGORrepl: ")
1851
                                (let ((state (%make-eval-state
1852
                                              (tree-walker
1853
                                               (read-from-string (fix-backspace (read-line current-input))))
1854
                                              env)))
1855
                                  (newline)
1856
                                  (let ((state (%eval-partial state 0)))
1857
                                    (let ((cond (%car (%cdr state))))
1858
                                      (newline)
1859
                                      (%if (igorev-state-huge-success? state)
1860
                                           (%progn
1861
                                            (display "Result: ")
1862
                                            (print (igorev-state-result state)))
1863
                                           (%progn
1864
                                            (show-error-message state)
1865
                                            (debug state)))
1866
                                      (newline)
1867
                                      (%if *igorrepl-continue*
1868
                                           (%if (%num-eq? n 1)
1869
                                                %t
1870
                                                (igorrepl (%if (%num-eq? n 0) 0 (1- n)) env))
1871
                                           nil)))))))
1872
 
1873
 
1874
 
1875
   ;;(intern-symbols %symbol-table)
1876
 
1877
   (display "boot program $Rev: 1441 $")
1878
   (newline)
1879
 
1880
   (%define
1881
    'looptyloop
1882
    (%lambda
1883
     looptyloop ()
1884
     (let ((state (%make-eval-state '(igorrepl 0 (new-environment (%current-environment)))
1885
                                    (%current-environment))))
1886
       (let ((new-state (%eval-partial state 0)))
1887
         (%if (igorev-state-huge-success? new-state)
1888
              (%progn
1889
               (display "Happy Happy Joy Joy")
1890
               (newline))
1891
              (%progn
1892
               (newline)
1893
               (display "ERROR IN TOP-LEVEL REPL")
1894
               (newline)
1895
               (show-error-message new-state)
1896
               (looptyloop)))))))
1897
   (looptyloop)
1898
))
1899
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.