├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── assets ├── index.html ├── main.rkt ├── main.wasm └── main.wat ├── compiler.rkt ├── info.rkt ├── main.rkt └── scribblings └── wracket.scrbl /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#* 3 | .\#* 4 | .DS_Store 5 | compiled/ 6 | /doc/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | # Based from: https://github.com/greghendershott/travis-racket 4 | 5 | # Optional: Remove to use Travis CI's older infrastructure. 6 | sudo: false 7 | 8 | env: 9 | global: 10 | # Supply a global RACKET_DIR environment variable. This is where 11 | # Racket will be installed. A good idea is to use ~/racket because 12 | # that doesn't require sudo to install and is therefore compatible 13 | # with Travis CI's newer container infrastructure. 14 | - RACKET_DIR=~/racket 15 | matrix: 16 | # Supply at least one RACKET_VERSION environment variable. This is 17 | # used by the install-racket.sh script (run at before_install, 18 | # below) to select the version of Racket to download and install. 19 | # 20 | # Supply more than one RACKET_VERSION (as in the example below) to 21 | # create a Travis-CI build matrix to test against multiple Racket 22 | # versions. 23 | - RACKET_VERSION=6.0 24 | - RACKET_VERSION=6.1 25 | - RACKET_VERSION=6.1.1 26 | - RACKET_VERSION=6.2 27 | - RACKET_VERSION=6.3 28 | - RACKET_VERSION=6.4 29 | - RACKET_VERSION=6.5 30 | - RACKET_VERSION=6.6 31 | - RACKET_VERSION=6.7 32 | - RACKET_VERSION=6.8 33 | - RACKET_VERSION=6.9 34 | - RACKET_VERSION=6.10 35 | - RACKET_VERSION=6.10.1 36 | - RACKET_VERSION=6.11 37 | - RACKET_VERSION=HEAD 38 | 39 | matrix: 40 | allow_failures: 41 | # - env: RACKET_VERSION=HEAD 42 | fast_finish: true 43 | 44 | before_install: 45 | - git clone https://github.com/greghendershott/travis-racket.git ~/travis-racket 46 | - cat ~/travis-racket/install-racket.sh | bash # pipe to bash not sh! 47 | - export PATH="${RACKET_DIR}/bin:${PATH}" #install-racket.sh can't set for us 48 | 49 | install: 50 | - raco pkg install --deps search-auto 51 | 52 | before_script: 53 | 54 | # Here supply steps such as raco make, raco test, etc. You can run 55 | # `raco pkg install --deps search-auto` to install any required 56 | # packages without it getting stuck on a confirmation prompt. 57 | script: 58 | - raco test -x -p wracket 59 | 60 | after_success: 61 | - raco setup --check-pkg-deps --pkgs wracket 62 | - raco pkg install --deps search-auto cover cover-coveralls 63 | - raco cover -b -f coveralls -d $TRAVIS_BUILD_DIR/coverage . 64 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | wracket 2 | Copyright (c) 2017 Simon Schauß 3 | 4 | This package is distributed under the GNU Lesser General Public 5 | License (LGPL). This means that you can link wracket into proprietary 6 | applications, provided you follow the rules stated in the LGPL. You 7 | can also modify this package; if you distribute a modified version, 8 | you must distribute it under the terms of the LGPL, which in 9 | particular means that you must release the source code for the 10 | modified software. See http://www.gnu.org/copyleft/lesser.html 11 | for more information. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | wracket 2 | ======= 3 | README text here. 4 | -------------------------------------------------------------------------------- /assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | wracket 7 | 8 | 9 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /assets/main.rkt: -------------------------------------------------------------------------------- 1 | (module 2 | (define- (fib n) 3 | (if (<= n 2) 4 | 1 5 | (+ (fib (- n 1)) (fib (- n 2))))) 6 | (define+ (main n) (fib n))) 7 | -------------------------------------------------------------------------------- /assets/main.wasm: -------------------------------------------------------------------------------- 1 | asm`main 2 | ' ALA Ak Akj    -------------------------------------------------------------------------------- /assets/main.wat: -------------------------------------------------------------------------------- 1 | (module (func $fib (param $n i32) (result i32) (return (if (result i32) (i32.le_s (get_local $n) (i32.const 2)) (then (i32.const 1)) (else (i32.add (call $fib (i32.sub (get_local $n) (i32.const 1))) (call $fib (i32.sub (get_local $n) (i32.const 2)))))))) (func $main (param $n i32) (result i32) (return (call $fib (get_local $n)))) (export "main" (func $main))) -------------------------------------------------------------------------------- /compiler.rkt: -------------------------------------------------------------------------------- 1 | #lang at-exp racket 2 | (provide compile-file) 3 | 4 | (define (compile-file filename) 5 | (let* ([i (open-input-file filename)] 6 | [f (string-replace filename "rkt" "wat")] 7 | [o (open-output-file f #:exists 'replace)]) 8 | (let-values ([(c env) (compile (read i) (list))]) 9 | (write-string c o)))) 10 | 11 | (define (compile d env) 12 | (match d 13 | [`,(? number?) (compile-number d env)] 14 | [`,(? symbol?) (compile-symbol d env)] 15 | [`(+ ,l ,r) (compile-add l r env)] 16 | [`(- ,l ,r) (compile-minus l r env)] 17 | [`(* ,l ,r) (compile-multiply l r env)] 18 | [`(/ ,l ,r) (compile-divide l r env)] 19 | [`(= ,l ,r) (compile-equal l r env)] 20 | [`(!= ,l ,r) (compile-unequal l r env)] 21 | [`(> ,l ,r) (compile-greater l r env)] 22 | [`(>= ,l ,r) (compile-greater-equal l r env)] 23 | [`(< ,l ,r) (compile-less l r env)] 24 | [`(<= ,l ,r) (compile-less-equal l r env)] 25 | [`(define- (,name ,params ...) ,body ...) (compile-define- name params body env)] 26 | [`(define+ (,name ,params ...) ,body ...) (compile-define+ name params body env)] 27 | [`(let [,name ,exp] ,body ...) (compile-let name exp body env)] 28 | [`(if ,cond ,exp1 ,exp2) (compile-if-then-else cond exp1 exp2 env)] 29 | [`(module ,body ...) (compile-module body env)] 30 | [`(,name ,params ...) (compile-call name params env)])) 31 | 32 | (define (compile* exps env) 33 | (letrec ([compile* (lambda (exps env result) 34 | (if (empty? exps) 35 | (values result env) 36 | (let-values ([(exp env) (compile (first exps) env)]) 37 | (compile* (rest exps) env (append result (list exp))))))]) 38 | (compile* exps env '()))) 39 | 40 | (define (compile-number n env) 41 | (values @~a{(i32.const @n)} env)) 42 | 43 | (define (compile-symbol s env) 44 | (values @~a{(get_local $@s)} env)) 45 | 46 | (define (compile-add l r env) 47 | (let*-values ([(l env) (compile l env)] 48 | [(r env) (compile r env)]) 49 | (values @~a{(i32.add @l @r)} env))) 50 | 51 | (define (compile-minus l r env) 52 | (let*-values ([(l env) (compile l env)] 53 | [(r env) (compile r env)]) 54 | (values @~a{(i32.sub @l @r)} env))) 55 | 56 | (define (compile-multiply l r env) 57 | (let*-values ([(l env) (compile l env)] 58 | [(r env) (compile r env)]) 59 | (values @~a{(i32.mul @l @r)} env))) 60 | 61 | (define (compile-divide l r env) 62 | (let*-values ([(l env) (compile l env)] 63 | [(r env) (compile r env)]) 64 | (values @~a{(i32.div @l @r)} env))) 65 | 66 | (define (compile-equal l r env) 67 | (let*-values ([(l env) (compile l env)] 68 | [(r env) (compile r env)]) 69 | (values @~a{(i32.eq @l @r)} env))) 70 | 71 | (define (compile-unequal l r env) 72 | (let*-values ([(l env) (compile l env)] 73 | [(r env) (compile r env)]) 74 | (values @~a{(i32.ne @l @r)} env))) 75 | 76 | (define (compile-greater l r env) 77 | (let*-values ([(l env) (compile l env)] 78 | [(r env) (compile r env)]) 79 | (values @~a{(i32.gt_s @l @r)} env))) 80 | 81 | (define (compile-greater-equal l r env) 82 | (let*-values ([(l env) (compile l env)] 83 | [(r env) (compile r env)]) 84 | (values @~a{(i32.ge_s @l @r)}) env)) 85 | 86 | (define (compile-less l r env) 87 | (let*-values ([(l env) (compile l env)] 88 | [(r env) (compile r env)]) 89 | (values @~a{(i32.lt_s @l @r)} env))) 90 | 91 | (define (compile-less-equal l r env) 92 | (let*-values ([(l env) (compile l env)] 93 | [(r env) (compile r env)]) 94 | (values @~a{(i32.le_s @l @r)} env))) 95 | 96 | (define (compile-let name exp body env) 97 | (let*-values ([(exp env) (compile exp env)] 98 | [(body env) (compile* body env)] 99 | [(body) (string-join body)] 100 | [(env) (cons name env)]) 101 | (values @~a{(block (result i32) (set_local $@name @exp) @body)} env))) 102 | 103 | (define (compile-define- name params body env) 104 | (let*-values ([(body env) (compile* body env)] 105 | [(body) (string-join body)] 106 | [(params) (string-join (map (lambda (param) @~a{(param $@param i32)}) params))] 107 | [(locals) (string-join (map (lambda (name) @~a{(local $@name i32)}) env))]) 108 | (values @~a{(func $@name @params (result i32) @locals (return @body))} env))) 109 | 110 | (define (compile-define+ name params body env) 111 | (let*-values ([(body env) (compile* body env)] 112 | [(body) (string-join body)] 113 | [(params) (string-join (map (lambda (param) @~a{(param $@param i32)}) params))] 114 | [(locals) (string-join (map (lambda (name) @~a{(local $@name i32)}) env))]) 115 | (values @~a{(func $@name @params (result i32) @locals (return @body)) (export "@name" (func $@name))} env))) 116 | 117 | (define (compile-if-then-else cond exp1 exp2 env) 118 | (let*-values ([(cond env) (compile cond env)] 119 | [(exp1 env) (compile exp1 env)] 120 | [(exp2 env) (compile exp2 env)]) 121 | (values @~a{(if (result i32) @cond (then @exp1) (else @exp2))} env))) 122 | 123 | (define (compile-param name env) 124 | (values @~a{(param $@name i32)} env)) 125 | 126 | (define (compile-module body env) 127 | (let*-values ([(body env) (compile* body env)] 128 | [(body) (string-join body)]) 129 | (values @~a{(module @body)} env))) 130 | 131 | (define (compile-call name params env) 132 | (let*-values ([(params env) (compile* params env)] 133 | [(params) (string-join params)]) 134 | (values @~a{(call $@name @params)} env))) -------------------------------------------------------------------------------- /info.rkt: -------------------------------------------------------------------------------- 1 | #lang info 2 | (define collection "wracket") 3 | (define deps '("base")) 4 | (define build-deps '("scribble-lib" "racket-doc" "rackunit-lib")) 5 | (define scribblings '(("scribblings/wracket.scrbl" ()))) 6 | (define pkg-desc "Lisp-like language to WebAssembly") 7 | (define version "0.0") 8 | (define pkg-authors '(Simon Schauß)) 9 | -------------------------------------------------------------------------------- /main.rkt: -------------------------------------------------------------------------------- 1 | #lang racket/base 2 | 3 | (module+ test 4 | (require rackunit)) 5 | 6 | ;; Notice 7 | ;; To install (from within the package directory): 8 | ;; $ raco pkg install 9 | ;; To install (once uploaded to pkgs.racket-lang.org): 10 | ;; $ raco pkg install <> 11 | ;; To uninstall: 12 | ;; $ raco pkg remove <> 13 | ;; To view documentation: 14 | ;; $ raco docs <> 15 | ;; 16 | ;; For your convenience, we have included a LICENSE.txt file, which links to 17 | ;; the GNU Lesser General Public License. 18 | ;; If you would prefer to use a different license, replace LICENSE.txt with the 19 | ;; desired license. 20 | ;; 21 | ;; Some users like to add a `private/` directory, place auxiliary files there, 22 | ;; and require them in `main.rkt`. 23 | ;; 24 | ;; See the current version of the racket style guide here: 25 | ;; http://docs.racket-lang.org/style/index.html 26 | 27 | ;; Code here 28 | 29 | (module+ test 30 | ;; Tests to be run with raco test 31 | ) 32 | 33 | (module+ main 34 | ;; Main entry point, executed when run with the `racket` executable or DrRacket. 35 | (require racket/cmdline 36 | wracket/compiler) 37 | (let ([filename (command-line #:args (filename) filename)]) 38 | (compile-file filename))) 39 | -------------------------------------------------------------------------------- /scribblings/wracket.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | @require[@for-label[wracket 3 | racket/base]] 4 | 5 | @title{wracket} 6 | @author{Simon Schauß} 7 | 8 | @defmodule[wracket] 9 | 10 | Package Description Here 11 | --------------------------------------------------------------------------------