5 (define (define-op1 six-id id type-rule constant-fold code-gen)
7 (cons (make-op1 six-id id type-rule constant-fold code-gen)
10 (define (define-op2 six-id id type-rule constant-fold code-gen)
12 (cons (make-op2 six-id id type-rule constant-fold code-gen)
15 ;; no need for type checks, every type sixpic supports can be casted to / from
16 ;; ints (except void, but this is a non-issue) and promotion (by padding) and
17 ;; truncation is done at the cfg level
18 ;; TODO really ignore the void issue ? assigning the "result" of a void function to an int variable should be an error
19 (define (type-rule-int-op1 ast)
20 (expr-type (subast1 ast)))
22 (define (largest t1 t2)
23 (if (> (type->bytes t1) (type->bytes t2))
27 (define (type-rule-int-op2 ast)
28 ;; used for any binary operation involving two integers where the result is
29 ;; of the size of the biggest operand (subtraction, bitwise operations, ...)
30 (let ((t1 (expr-type (subast1 ast)))
31 (t2 (expr-type (subast2 ast))))
34 (define (type-rule-assign ast)
35 (let ((t1 (expr-type (subast1 ast))))
36 ;; the type of the rhs is irrelevant, since it will be promoted
37 ;; or truncated at the cfg level
40 (define (type-rule-int-comp-op2 ast)
41 'bool) ;; TODO why even bother ? anything can be casted to int to be used as argument here, old version is in garbage (and in version control) if needed
43 (define (type-rule-bool-op2 ast)
44 'bool) ;; TODO same here
46 (define-op1 'six.!x '!x
48 (lambda (ast) ;; TODO implement these ?
54 (define-op1 'six.++x '++x
55 ;; unlike addition, we do not need to add an extra byte just in case
56 ;; since the destination and the source are the same, we won't have any
57 ;; unexpected truncation problems
64 (define-op1 'six.x++ 'x++
71 (define-op1 'six.--x '--x
78 (define-op1 'six.x-- 'x--
85 (define-op1 'six.~x '~x
92 (define-op2 'six.x%y 'x%y
94 ;; if we know the second operand, we can have an upper bound on the size
96 (if (literal? (subast1 ast))
97 ;; the number of bits needed by the result is lg(y)
98 (bytes->type (ceiling (/ (log y) (log 2) 8)))
99 ;; fall back to the general case
100 (type-rule-int-op2 ast)))
106 (define-op2 'six.x*y 'x*y
107 ;; products can be as wide as the sum of the widths of the operands
109 (let ((l1 (type->bytes (expr-type (subast1 ast))))
110 (l2 (type->bytes (expr-type (subast2 ast)))))
111 (bytes->type (+ l1 l2))))
117 (define-op1 'six.*x '*x
119 'byte) ; we only have byte arrays
125 (define-op2 'six.index 'index
127 'byte) ; we only have byte arrays
133 (define-op2 'six.x/y 'x/y
135 ;; if we know the second operand, we can have an upper bound on the size
137 (if (literal? (subast1 ast))
138 ;; for every byte over 1 in the length of y, we can remove a byte from
140 ;; ex : the smallest value which needs 2 bytes to encode is 256, and
141 ;; dividing by 256 is equivalent to truncating the 8 lowest bits, and
143 (let (((l1 (type->bytes (expr-type (subast1 ast))))
144 (l2 (ceiling (/ (log y) (log 2) 8)))))
145 (bytes->type (- (max l1 l2) (- l2 1))))
146 ;; fall back to the general case
147 (type-rule-int-op2 ast)))
154 (define-op2 'six.x+y 'x+y
156 (let ((l1 (type->bytes (expr-type (subast1 ast))))
157 (l2 (type->bytes (expr-type (subast2 ast)))))
158 ;; the extra byte is needed in some cases
159 ;; for example : 200 + 200 = 400
160 ;; both operands are 1 byte wide, but the result is 2 bytes wide
161 (bytes->type (+ (max l1 l2) 1))))
167 (define-op1 'six.+x '+x
174 (define-op2 'six.x-y 'x-y
181 (define-op1 'six.-x '-x
188 (define-op2 'six.x<<y 'x<<y ;; TODO for the general case, would give scary results (a single byte for y can still mean a shift by 255)
190 (if (not (literal? (subast2 ast)))
191 (error "only shifting by literals is supported"))
192 (let ((l1 (type->bytes (expr-type (subast1 ast))))
193 (v2 (literal-val (subast2 ast))))
194 ;; we might have to add some bytes to the result
195 (bytes->type (+ l1 (ceiling (/ v2 8))))))
201 (define-op2 'six.x>>y 'x>>y
203 (if (not (literal? (subast2 ast)))
204 (error "only shifting by literals is supported"))
205 (let ((l1 (type->bytes (expr-type (subast1 ast))))
206 (v2 (literal-val (subast2 ast))))
207 ;; we might be able to shave some bytes off
208 (bytes->type (- l1 (floor (/ v2 8))))))
214 (define-op2 'six.x<y 'x<y
215 type-rule-int-comp-op2
221 (define-op2 'six.x<=y 'x<=y
222 type-rule-int-comp-op2
228 (define-op2 'six.x>y 'x>y
229 type-rule-int-comp-op2
235 (define-op2 'six.x>=y 'x>=y
236 type-rule-int-comp-op2
242 (define-op2 'six.x!=y 'x!=y
243 type-rule-int-comp-op2
249 (define-op2 'six.x==y 'x==y
250 type-rule-int-comp-op2
256 (define-op2 'six.x&y 'x&y
263 (define-op1 'six.&x '&x
271 (define-op2 'six.x^y 'x^y
278 (define-op2 '|six.x\|y| '|x\|y|
285 (define-op2 'six.x&&y 'x&&y
292 (define-op2 '|six.x\|\|y| '|x\|\|y|
299 (define-op2 'six.x?y:z 'x?y:z
307 (define-op2 'six.x:y 'x:y
315 (define-op2 'six.x%=y 'x%=y ;; TODO these don't work
322 (define-op2 'six.x&=y 'x&=y
329 (define-op2 'six.x*=y 'x*=y
336 (define-op2 'six.x+=y 'x+=y
343 (define-op2 'six.x-=y 'x-=y
350 (define-op2 'six.x/=y 'x/=y
357 (define-op2 'six.x<<=y 'x<<=y
364 (define-op2 'six.x=y 'x=y
371 (define-op2 'six.x>>=y 'x>>=y
378 (define-op2 'six.x^=y 'x^=y
385 (define-op2 '|six.x\|=y| '|x\|=y|
392 (define-op2 'six.x:=y 'x:=y
400 (define-op2 '|six.x,y| '|x,y|
408 (define-op2 'six.x:-y 'x:-y
416 (define (operation? source)
418 (let ((x (car source)))
419 (let loop ((lst operators))
422 ((eq? (op-six-id (car lst)) x)
425 (loop (cdr lst))))))))