-
Notifications
You must be signed in to change notification settings - Fork 2
/
kamby.scm
99 lines (78 loc) · 3.01 KB
/
kamby.scm
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
(define (tokenize script-text)
(let ((tkns (list "")) (in-str? #f))
(define (append-str! str)
(set! tkns (cons (string-append (car tkns) str) (cdr tkns))))
(define (add-tkn! . strs)
(if (string=? (car tkns) "") (set! tkns (cdr tkns)))
(set! tkns (append (reverse strs) tkns)))
(define (handle-char char)
(let ((str (string char)))
(if (and in-str? (not (eq? char #\"))) (append-str! str)
(case char
((#\") (set! in-str? (not in-str?)) (append-str! str))
((#\( #\[ #\{) (add-tkn! str ""))
((#\; #\) #\] #\}) (add-tkn! str))
((#\space #\newline) (add-tkn! ""))
(else (append-str! str))))))
(for-each handle-char (string->list script-text))
(reverse tkns)))
(define (transpile old-tkns)
(let ((tkns (list "(")))
(define (add-tkn! . strs)
(set! tkns (append (reverse strs) tkns)))
(define (swap lst)
(cons (cadr lst) (cons (car lst) (cddr lst))))
(define (handle-tkn tkn)
(cond
((string=? tkn "") 0)
((string=? tkn "{") (if (string=? (car tkns) ")\n(")
(set! tkns (cdr tkns))) (add-tkn! "\n( begin\n("))
((string=? tkn "}") (set! tkns (cdr tkns)) (add-tkn! ") )" ")\n("))
((string=? tkn "[") (add-tkn! "( list"))
((string=? tkn "]") (add-tkn! ")"))
((string=? tkn ";") (add-tkn! ")\n("))
((string=? tkn "=") (add-tkn! "=!") (set! tkns (swap tkns)))
((member tkn (list "==" "!=" "&&" "||" "+" "-" "*" "/"
"<" ">" "<=" ">="))
(add-tkn! tkn) (set! tkns (swap tkns)))
(else (add-tkn! tkn))))
(for-each handle-tkn old-tkns)
(set! tkns (cdr tkns))
(add-tkn! ")")
(apply string-append(map (lambda (s) (string-append s " ")) (reverse tkns)))))
(define input-text
(let loop ((char (read-char)) (acc ""))
(if (eof-object? char) acc
(loop (read-char) (string-append acc (make-string 1 char))))))
(define (eval-string str)
(let ((port (open-input-string str)))
(do ((expr (read port) (read port)))
((eof-object? expr))
(eval expr (interaction-environment)))))
; Language extensions
(eval-string "\
(define-syntax ==
(syntax-rules () ((_ a b) (= a b))))
(define-syntax !=
(syntax-rules () ((_ a b) (not (= a b)))))
(define-syntax &&
(syntax-rules () ((_ a b) (and a b))))
(define-syntax ||
(syntax-rules () ((_ a b) (or a b))))
(define-syntax =!
(syntax-rules () ((_ key val) (set! key val))))
(define-syntax var
(syntax-rules (=!)
((_ =! key val) (define key val))
((_ key) (define key))))
(define-syntax func
(syntax-rules () ((_ key args body) (define (key . args) body))))
(define-syntax print
(syntax-rules () ((_ arg ...) (begin (display arg) ... (newline)))))
(define-syntax include-script
(syntax-rules ()
((_ path)
(let ((file-content (call-with-input-file path get-string-all)))
(eval-string (transpile (tokenize file-content)))))))
\n")
(eval-string (transpile (tokenize input-text)))