File: define-primitive.scm

package info (click to toggle)
scheme48 1.9.2-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 18,232 kB
  • sloc: lisp: 88,907; ansic: 87,519; sh: 3,224; makefile: 771
file content (143 lines) | stat: -rw-r--r-- 5,124 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
; Part of Scheme 48 1.9.  See file COPYING for notices and license.

; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Martin Gasbichler

; These are hacked to ensure that all calls to INPUT-TYPE-PREDICATE and
; INPUT-TYPE-COERCION are evaluated at load time (because they don't
; have readily reconstructed types).

(define-syntax define-primitive
  (syntax-rules ()
    ((define-primitive opcode input-types action)
     (define-consing-primitive opcode input-types #f action))
    ((define-primitive opcode input-types action returner)
     (define-consing-primitive opcode input-types #f action returner))))

(define-syntax define-consing-primitive
  (syntax-rules ()
    ((define-consing-primitive opcode input-types space-proc action)
     (let ((proc (primitive-procedure-action input-types space-proc action)))
       (define-opcode opcode (proc))))
    ((define-consing-primitive opcode input-types space-proc action returner)
     (let ((proc (primitive-procedure-action input-types space-proc action returner)))
       (define-opcode opcode (proc))))))
  
(define-syntax primitive-procedure-action
  (lambda (exp rename compare)
    (destructure (((p-p-b input-types space-proc action . returner-option) exp))
      (let* ((nargs (length input-types))
	     (%action       (rename 'action))
	     (%key          (rename 'key))
	     (%ensure-space (rename 'ensure-space))
	     (%*val*        (rename '*val*))
	     (%arg2         (rename 'arg2))
	     (%arg3         (rename 'arg3))
	     (%arg4         (rename 'arg4))
	     (%arg5         (rename 'arg5))
	     (%pop          (rename 'pop))
	     (%let          (rename 'let))
	     (%let*         (rename 'let*))
	     (%lambda       (rename 'lambda))
	     (%if           (rename 'if))
	     (%and          (rename 'and))
	     (%goto         (rename 'goto))
	     (%input-type-predicate (rename 'input-type-predicate))
	     (%input-type-coercion  (rename 'input-type-coercion))
	     (%raise-exception      (rename 'raise-exception))
	     (%wrong-type-argument  (rename 'wrong-type-argument))
	     (shorten (lambda (l1 l2)
			(map (lambda (x1 x2) x2 x1) l1 l2)))
	     (places (reverse (shorten (list %*val* %arg2 %arg3 %arg4 %arg5)
				       input-types)))
	     (preds (reverse (shorten (map rename
					   '(pred1 pred2 pred3 pred4 pred5))
				      input-types)))
	     (x->ys (reverse (shorten (map rename
					   '(x->y1 x->y2 x->y3 x->y4 x->y5))
				      input-types))))
	(if (> nargs 5)
	    (error "time to add more arguments to DEFINE-PRIMITIVE"))
	`(,%let (,@(map (lambda (type pred)
			  `(,pred (,%input-type-predicate ,type)))
			input-types
			preds)
		 ,@(map (lambda (type x->y)
			  `(,x->y (,%input-type-coercion ,type)))
			input-types
			x->ys)
		 (,%action ,action))
	   (,%lambda ()
	     (,%let* (,@(if space-proc
			  `((,%key (,%ensure-space (,space-proc ,%*val*))))
			  '())
		    ,@(if (>= nargs 2) `((,%arg2 (,%pop))) `())
		    ,@(if (>= nargs 3) `((,%arg3 (,%pop))) `())
		    ,@(if (>= nargs 4) `((,%arg4 (,%pop))) `())
		    ,@(if (>= nargs 5) `((,%arg5 (,%pop))) `())
		    )
	       (,%if (,%and ,@(map (lambda (pred place)
				     `(,pred ,place))
				   preds
				   places))
		     ,(let ((yow `(,%action
				   ,@(map (lambda (x->y place)
					    `(,x->y ,place))
					  x->ys
					  places)
				   ,@(if space-proc `(,%key) '()))))
			(if (null? returner-option)
			    yow
			    `(,%goto ,(car returner-option) ,yow)))
		     (,%raise-exception ,%wrong-type-argument
					0
					. ,places)))))))))

;----------------
; Checking inputs and coercing results

(define (input-type pred coercer)  ;Alonzo wins
  (lambda (f) (f pred coercer)))

(define (input-type-predicate type) (type (lambda (x y) y x)))
(define (input-type-coercion type)  (type (lambda (x y) x y)))

(define (no-coercion x) x)

(define any->         (input-type (lambda (x) x #t) no-coercion))
(define fixnum->      (input-type fixnum?      extract-fixnum))
(define char->        (input-type vm-char?     extract-char))
(define char-scalar-value-> (input-type vm-char? vm-char->scalar-value))
(define vm-char->     (input-type vm-char?     no-coercion))
(define boolean->     (input-type vm-boolean?  extract-boolean))
(define location->    (input-type location?    no-coercion))
(define string->      (input-type vm-string?   no-coercion))
(define vector->      (input-type vm-vector?   no-coercion))
(define record-type-> (input-type possibly-record-type? no-coercion))
(define code-vector-> (input-type code-vector? no-coercion))
(define vm-integer->  (input-type (lambda (x) (or (fixnum? x)
						  (bignum? x))) no-coercion))
; Output coercion

(define (return val)
  (set! *val* val)
  (goto continue 0))

(define return-any return)

(define (return-boolean x)
  (goto return (enter-boolean x)))

(define (return-fixnum x)
  (goto return (enter-fixnum x)))

(define (return-scalar-value-char x)
  (goto return (scalar-value->vm-char x)))

(define (return-unspecific x)
  x ;ignored
  (goto return unspecific-value))

(define (no-result)
  (goto return unspecific-value))