Overview
Comment: | add support for conditionals, array indexing, and reference-taking |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
844294c3a498c4ada3ad69a274503e6f |
User & Date: | lexi on 2019-07-24 22:36:50 |
Other Links: | manifest | tags |
Context
2019-07-25
| ||
11:06 | add nkvd.c and make infra check-in: 7ba40af07e user: lexi tags: trunk | |
2019-07-24
| ||
22:36 | add support for conditionals, array indexing, and reference-taking check-in: 844294c3a4 user: lexi tags: trunk | |
2019-07-23
| ||
12:32 | add sexcp check-in: 520b38deac user: lexi tags: trunk | |
Changes
Modified sexpc/example.cse from [58b3a515c7] to [d3af63ab24].
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
|
; (@ … ) introduces a block of Scheme code that ; is evaluated in the program's environment, but ; whose value is silently ignored. this makes it ; good for defining globals you intend to use ; later in the program with (* … ) or (= … ) ; blocks - see the paragraph below (define (sayl str) `(add-> total (call write 1 ; the return value of a scheme expression will ; be evaluated just like any other expression ; and transformed into C code, so we can rely ; on existing syntax instead of haven't to ; generate raw strings of C ,(string-append str "\\n") ,(+ 1 (string-length str)))))) (decl sayhello ((ptr char) → int)) (def (total size_t) 0) (def (main int (argc int) (argv (array (ptr char)))) (ret (call sayhello "dumbass"))) (def (sayhello int (name (ptr char))) (* sayl "hello…") ; a list prefixed with * indicates that it ; should be evaluated as a scheme expression ; and its result then processed, instead of ; being processed directly like (call) or ................................................................................ ; (def). scheme expressions may be inserted ; anywhere a normal sexpc expression can. or ; we could instead write (= (sayl "hello…")) ; to accomplish the same effect; (= … ) is ; really just shorthand for (* begin … ) (call write 1 name (call strlen name)) (ret total) ) |
|
>
>
>
|
|
|
>
>
>
|
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
|
; (@ … ) introduces a block of Scheme code that ; is evaluated in the program's environment, but ; whose value is silently ignored. this makes it ; good for defining globals you intend to use ; later in the program with (* … ) or (= … ) ; blocks - see the paragraph below (define (sayl str) `(add-> total (call write 1 ; the return value of a scheme expression will ; be evaluated just like any other expression ; and transformed into C code, so we can rely ; on existing syntax instead of haven't to ; generate raw strings of C ,(string-append str "\\n") ,(+ 1 (string-length str)))))) (decl sayhello ((ptr char) → int)) (decl usage (() => ())) (def (total size_t) 0) (def (main int (argc int) (argv (array (ptr char)))) (def (voidptr (ptr ())) (cast (ptr ()) argv)) (cond ((neq argc 2) (call usage)) (else (call sayhello (idx argv 1))))) (def (sayhello int (name (ptr char))) (* sayl "hello…") ; a list prefixed with * indicates that it ; should be evaluated as a scheme expression ; and its result then processed, instead of ; being processed directly like (call) or ................................................................................ ; (def). scheme expressions may be inserted ; anywhere a normal sexpc expression can. or ; we could instead write (= (sayl "hello…")) ; to accomplish the same effect; (= … ) is ; really just shorthand for (* begin … ) (call write 1 name (call strlen name)) (ret total)) (def (usage void ()) (* sayl "usage: example <name>")) |
Modified sexpc/sexpc.scm from [a27b738777] to [46b6c9a575].
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 .. 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 ... 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 ... 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
(import (chicken process-context)) (import (chicken condition)) (import (chicken pretty-print)) (import (chicken io)) (include "../scmlib/lisp-macro.scm") (: *code-depth* integer) (define *code-depth* 0) ; im sry (: indent (string -> string)) (define (indent str) (define (iterate n) (if (eq? n 0) str (string-append "\t" (iterate (- n 1))))) (iterate *code-depth*)) (define (first fst . lst) fst) (: string-reduce (list --> string)) (: words->string (list --> string)) (: separate (string list --> string)) (define (string-reduce lst) (foldl string-append "" lst)) (define (words->string lst) (foldl (lambda (a b) (string-append a " " b)) "" lst)) ................................................................................ (else (abort '(exn syntax declare))))) (define (c-define body) (cond ((and (list? (car body)) (>= (length body) 2)) (let ([contents (words->string (map (lambda(x) (eval-code #f x)) (cdr body)))]) (string-append (c-declare (car body)) (if (>= (length (car body)) 3) (string-append " {\n" contents "\n}") (string-append " = " contents))))) (else (abort '(exn syntax define))))) (: c-call-function (list -> string)) (define (c-call-function body) (unless (> (length body) 0) (abort '(exn parse call))) (string-append (eval-code #t (car body)) "(" (separate "," (map (lambda(x) (eval-code #t x)) (cdr body))) ")")) (define (c-cpp-include body) (case (length body) ((1) (if (string? (car body)) (string-append "#include \"" (car body) "\"\n") (abort '(exn syntax include)))) ((2) (if (and (eqv? (car body) 'sys) (string? (cadr body))) (string-append "#include <" (cadr body) ">\n") ................................................................................ ((and (list? a) (= (length a) 2)) ((eval-type (cadr a)) (car a))) ((list? a) ((eval-type a)"")) (else (abort '(exn syntax function-declare argument))))) (let ([arg-str (separate ", " (map parse-arg args))] [ret-fn (eval-type ret)]) (ret-fn (string-append (ensure-string name) "(" arg-str ")")))) (define-macro (with-deeper-context . body) `(begin (set! *code-depth* (+ 1 *code-depth*)) (first ,@body (set! *code-depth* (- *code-depth* 1)) ))) (: c-statement (string -> string)) (define (c-statement s) (indent (with-deeper-context (string-append s ";\n")))) (: eval-type ((or null symbol list) -> ((or symbol string) -> string))) (define (eval-type t) ; a type object is a function that is called with a name to ; generate a definition. this is necessary for the case of ; arrays and function pointers, which require special syntax (: simple ((or string symbol) --> string)) ................................................................................ ('uint (simple "unsigned int")) ('ulong (simple "unsigned long")) ('ullong (simple "unsigned long long")) ('llong (simple "long long")) ('ldouble (simple "long double")) ('u128 (simple "unsigned __int128_t")) ('s128 (simple "__int128_t")) (else (simple (symbol->string t))))) ((list? t) (parse-type t)) ((string? t) (simple t)) (else (abort '(exn syntax))))) (define (c-construct type name body) (string-append type " " name " {\n" (string-reduce (map (lambda(x) (indent (eval-code #f x))) body)) "\n}")) (define (c-fn-return body) (string-append "return " (string-reduce (map (lambda(x) (eval-code #t x)) body)))) (define (c-math-op op body) (unless (= 2 (length body)) (abort '(exn syntax math))) (string-append "((" (eval-code #t (car body)) ")" op "(" (eval-code #t (cadr body)) "))")) (define (inter s x) (print* "-- " s ": ") (pretty-print x) x) (: eval-code (boolean list -> string)) (define (eval-code inexpr data) (define (ctx x) inexpr (if (eq? inexpr #t) x (c-statement x))) (define (deepen n) (set! *code-depth* (+ *code-depth* n))) (: dispatch (list -> string)) (define (dispatch form body) (case form ('* (eval-code inexpr (evaluate-list body))) ('= (eval-code inexpr (evaluate-list (cons 'begin body)))) ('@ (eval (cons 'begin body)) "") ('use (c-cpp-include body)) ('def (first (c-statement (with-deeper-context (c-define body))) )) ('decl (first (c-statement (with-deeper-context (c-declare body))) )) ('call (ctx (c-call-function body))) ('list (first (string-append "{" (separate "," (map (lambda(x) (eval-code #t x)) body)) "}") )) ('struct (first (ctx (c-construct "struct" (car form) (cdr form))) )) ('enum (first (ctx (c-construct "enum" (car form) (cdr form))) )) ('ret (c-statement (c-fn-return body))) ('add (c-math-op "+" body)) ('add-> (ctx (c-math-op "+=" body))) ('sub (c-math-op "-" body)) ('sub-> (ctx (c-math-op "-=" body))) ('mul (c-math-op "*" body)) ('mul-> (ctx (c-math-op "*=" body))) ('div (c-math-op "/" body)) ('div-> (ctx (c-math-op "/=" body))) ('== (c-math-op "==" body)) ('-> (ctx (c-math-op "=" body))) ('→ (ctx (c-math-op "=" body))) ('; ";") (else (string-append "<UNFOUND FORM " (symbol->string form) ">")) ))) (cond ((null? data) "") ((symbol? data) (symbol->string data)) ((string? data) (string-append "\"" data "\"")) |
< < < < < < < < < | > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < | > | | | | | > > > > > > > > | < | | > > > | | | | | | | | > | > > > > > | | |
24 25 26 27 28 29 30 31 32 33 34 35 36 37 .. 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 ... 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 ... 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
(import (chicken process-context)) (import (chicken condition)) (import (chicken pretty-print)) (import (chicken io)) (include "../scmlib/lisp-macro.scm") (define (first fst . lst) fst) (: string-reduce (list --> string)) (: words->string (list --> string)) (: separate (string list --> string)) (define (string-reduce lst) (foldl string-append "" lst)) (define (words->string lst) (foldl (lambda (a b) (string-append a " " b)) "" lst)) ................................................................................ (else (abort '(exn syntax declare))))) (define (c-define body) (cond ((and (list? (car body)) (>= (length body) 2)) (let ([contents (words->string (map (lambda(x) (eval-code #f x)) (cdr body)))]) (string-append (c-declare (car body)) (if (>= (length (car body)) 3) (string-append " {" contents "}") (string-append " = " contents))))) (else (abort '(exn syntax define))))) (: c-call-function (list -> string)) (define (c-call-function body) (unless (> (length body) 0) (abort '(exn parse call))) (string-append (eval-code #t (car body)) "(" (separate "," (map (lambda(x) (eval-code #t x)) (cdr body))) ")")) (: c-array-index (list -> string)) (define (c-array-index body) (unless (= (length body) 2) (abort '(exn parse call))) (string-append (eval-code #t (car body)) "[" (eval-code #t (cadr body)) "]")) (: c-conditional (list -> string)) (define (c-conditional body) (unless (> (length body) 0) (abort '(exn parse cond))) (define (mk-block acc code) (string-append (if (eq? 'else (car code)) (string-append acc "else {") (string-append acc (if (equal? acc "") "if (" " else if (") (eval-code #t (car code)) ") {")) (string-reduce (map (lambda(x)(eval-code #f x)) (cdr code))) "}" )) (foldl mk-block "" body)) (define (c-cpp-include body) (case (length body) ((1) (if (string? (car body)) (string-append "#include \"" (car body) "\"\n") (abort '(exn syntax include)))) ((2) (if (and (eqv? (car body) 'sys) (string? (cadr body))) (string-append "#include <" (cadr body) ">\n") ................................................................................ ((and (list? a) (= (length a) 2)) ((eval-type (cadr a)) (car a))) ((list? a) ((eval-type a)"")) (else (abort '(exn syntax function-declare argument))))) (let ([arg-str (separate ", " (map parse-arg args))] [ret-fn (eval-type ret)]) (ret-fn (string-append (ensure-string name) "(" arg-str ")")))) (: c-statement (string -> string)) (define (c-statement s) (string-append s ";")) (: eval-type ((or null symbol list) -> ((or symbol string) -> string))) (define (eval-type t) ; a type object is a function that is called with a name to ; generate a definition. this is necessary for the case of ; arrays and function pointers, which require special syntax (: simple ((or string symbol) --> string)) ................................................................................ ('uint (simple "unsigned int")) ('ulong (simple "unsigned long")) ('ullong (simple "unsigned long long")) ('llong (simple "long long")) ('ldouble (simple "long double")) ('u128 (simple "unsigned __int128_t")) ('s128 (simple "__int128_t")) ('ptr (simple "void*")) (else (simple (symbol->string t))))) ((list? t) (parse-type t)) ((string? t) (simple t)) (else (abort '(exn syntax))))) (define (c-construct type name body) (string-append type " " name " {" (string-reduce (map (lambda(x) (eval-code #f x)) body)) "}")) (define (c-fn-return body) (string-append "return " (string-reduce (map (lambda(x) (eval-code #t x)) body)))) (define (c-binary-op op body) (unless (= 2 (length body)) (abort '(exn syntax binary-op))) (string-append "((" (eval-code #t (car body)) ")" op "(" (eval-code #t (cadr body)) "))")) (define (c-unary-op op body) (unless (= 1 (length body)) (abort '(exn syntax unary-op))) (string-append "(" op "(" (eval-code #t (car body)) "))")) (define (c-typecast body) (unless (= 2 (length body)) (abort '(exn syntax binary-op))) (string-append "((" ((eval-type (car body))"") ")" (eval-code #t (cadr body)) ")")) (define (wiretap s x) (print* "-- " s ": ") (pretty-print x) x) (: eval-code (boolean list -> string)) (define (eval-code inexpr data) (define (ctx x) inexpr (if (eq? inexpr #t) x (c-statement x))) (: dispatch (list -> string)) (define (dispatch form body) (case form ('* (eval-code inexpr (evaluate-list body))) ('= (eval-code inexpr (evaluate-list (cons 'begin body)))) ('@ (eval (cons 'begin body)) "") ('use (c-cpp-include body)) ('def (first (c-statement (c-define body))) ) ('decl (first (c-statement (c-declare body)) )) ('call (ctx (c-call-function body))) ('cond (c-statement (c-conditional body))) ('list (first (string-append "{" (separate "," (map (lambda(x) (eval-code #t x)) body)) "}") )) ('struct (first (ctx (c-construct "struct" (car form) (cdr form))) )) ('enum (first (ctx (c-construct "enum" (car form) (cdr form))) )) ('ret (c-statement (c-fn-return body))) ('cast (c-typecast body)) ('idx (c-array-index body)) ('add (c-binary-op "+" body)) ('add-> (ctx (c-binary-op "+=" body))) ('sub (c-binary-op "-" body)) ('sub-> (ctx (c-binary-op "-=" body))) ('mul (c-binary-op "*" body)) ('mul-> (ctx (c-binary-op "*=" body))) ('div (c-binary-op "/" body)) ('div-> (ctx (c-binary-op "/=" body))) ('ref (c-unary-op "&" body)) ('eq (c-binary-op "==" body)) ('neq (c-binary-op "!=" body)) ('gte (c-binary-op ">=" body)) ('lte (c-binary-op "<=" body)) ('lt (c-binary-op "<" body)) ('gt (c-binary-op ">" body)) ('-> (ctx (c-binary-op "=" body))) ('→ (ctx (c-binary-op "=" body))) ('; ";") (else (string-append "<UNFOUND FORM " (symbol->string form) ">")) ))) (cond ((null? data) "") ((symbol? data) (symbol->string data)) ((string? data) (string-append "\"" data "\"")) |
Modified sexpc/type-tests.scm from [47bc0863a3] to [3a7d364dcb].
17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
(const (ptr float)) (ptr int) (ullong schar -> (ptr (bool u128 -> ldouble))) (int -> chungus_t) (ptr (int -> chungus_t)) (array 5 (ptr (int -> chungus_t))) ((array 5 (ptr int)) -> (const (ptr (array 3 int)))) ; int (((*const (v(int (*(())[5])))))[3]) ; int (* const v(int *[5]))[3] (array (const (ptr (char u128 -> (ptr (array 5 bool)))))) (array 5 (const (ref char))))) (map test tests) |
< < | |
17 18 19 20 21 22 23 24 25 26 27 28 |
(const (ptr float))
(ptr int)
(ullong schar -> (ptr (bool u128 -> ldouble)))
(int -> chungus_t)
(ptr (int -> chungus_t))
(array 5 (ptr (int -> chungus_t)))
((array 5 (ptr int)) -> (const (ptr (array 3 int))))
(array (const (ptr (char u128 -> (ptr (array 5 bool))))))
(array 5 (const (ref char)))))
(map test tests)
|