blob: 332790909ccb6c982976208aaf734d5187d4f0ca (
plain) (
blame)
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
|
(define-library (csc linker)
(export link remove-labels make-label-map translate-labels)
(import (scheme base)
(only (csc encoding) encode)
(only (csc format) sprintf)
(only (csc hash-map)
hash-bytevector
insert
lookup
make-map)
(only (csc list)
enumerate
filter)
(only (csc match) match))
(begin
; A CSC bytecode program is a list of opcodes. An opcode is a symbol, or a 2
; item list of a symbol and an argument. The full list of opcodes can be
; found in encoding.csc.
(define (translate-labels program label-map)
(map
(lambda (x)
(match x
((i . ((! 'if) label))
; Compute offset from the current position. Subtract 1
; because the instruction pointer is incremented each
; time already.
(list 'if (- (lookup label-map label) i 1)))
((_ . ((! 'call) label))
(list 'call (lookup label-map label)))
((_ . opcode) opcode)))
(enumerate program)))
(lambda (i . opcode)
(match opcode
(((! 'if) label) #t)
(_ #f)))
(define (hash-string s)
(hash-bytevector (string->utf8 s)))
(define (cmp-strings s1 s2)
(cond
((string=? s1 s2) 0)
((string<? s1 s2) -1)
(else 1)))
(define (make-label-map program)
(let loop ((m (make-map hash-string cmp-strings))
(program program)
(i 0))
(match program
('() m)
((((! 'label) name) . tail)
(loop (insert m name i) tail i)) ; N.b.: i instead of (+ 1 i) because we're going to remove the labels later.
((_ . tail) (loop m tail (+ 1 i))))))
(define (remove-labels program)
(filter
(lambda (opcode)
(match opcode
(((! 'label) _) #f)
(_ #t)))
program))
(define (link . programs)
(let* ((program (apply append programs))
(label-map (make-label-map program)))
(encode (translate-labels (remove-labels program) label-map))))))
|