scheme.rs is a simple Scheme interpreter that implements considerably large subset of R5RS with some extensions from R7RS. No dependencies to any other Rust packages.
I was studying about compilers and interpreters. On the other hand I was trying to learn Rust. So I combined those two and this project has emerged. There are thousands of fast, mature and feature-rich Scheme interpreters that you can use. This project is not intended to be usable in production although I use it for my personal scripts and one can embed scheme.rs into ones project to provide scripting facilities.
;; FizzBuzz
(define (fizzbuzz x y)
(println
(cond ((= (modulo x 15) 0 ) "FizzBuzz")
((= (modulo x 3) 0 ) "Fizz")
((= (modulo x 5) 0 ) "Buzz")
(else x)))
(if (< x y) (fizzbuzz (+ x 1) y)))
(fizzbuzz 1 100)
;; Read a line from file and print it
(call-with-input-file "file.txt"
(λ (file)
(println (read-line file))))
;; Tail recursive fibanocci
(define (fib n)
(define (fib-helper a b n)
(if (= n 0) a
(fib-helper b (+ a b) (- n 1))))
(fib-helper 0 1 n))
(display (fib 60)) ; prints 1548008755920Run it using cargo:
cd scheme.rs
cargo runThis will fire up REPL. You can also run files directly:
cargo run filename.scm- Brackets can be used instead of parenthesis.
- Mutable lists
- Vectors (Lists are implemented in terms of vectors)
- Hygienic macros
call-with-current-continuationand it’s derivatives
Tail calls are optimized but this implementation does not reflect the
standard fully. Because there are no macros, functions like and, or,
cond, let etc. are implemented as separate procedures. So a procedure with
and in it’s tail call may blow up the stack. Regardless of macro
implementation, I may fix this in the future simply by expanding required
functions before evaluation.
- [ ] Mutable lists
- [ ] Hygienic macros
- [ ] Add useful SFRI’s like:
- [ ] SRFI-9 (Record types)
- [ ] SRFI-6 (String ports)
- [ ] SRFI-1 (List library, some of the functions are already available)
- [ ] SRFI-13 (String library)
- [ ] SRFI-88 (Keyword objects)
- Adding a basic VM with garbage collector may be a long term goal (which will allow implementation of cal/cc).
Fair amount of these functions are implemented in Rust.
| define | < | procedure? | char<=? |
| set! | > | boolean? | char>=? |
| λ | <= | char? | char-ci=? |
| lambda | >= | string? | char-ci<? |
| apply | = | integer? | char-ci>? |
| let | cond | exact? | char-ci<=? |
| let* | case | inexact? | char-ci>=? |
| letrec | and | number? | string=? |
| quote | or | pair? | string<? |
| quasiquote | cons | list? | string>? |
| unquote | car | output-port? | string<=? |
| eqv? | cdr | input-port? | string>=? |
| eq? | append | textual-port? | string-ci=? |
| equal? | list-copy | binary-port? | string-ci<? |
| + | string-append | not | string-ci>? |
| - | string-upcase | zero? | string-ci<=? |
| * | string-downcase | positive? | string-ci>=? |
| / | string-length | negative? | substring |
| remainder | char-upcase | odd? | string-ref |
| modulo | char-downcase | even? | string |
| numerator | char-upper-case? | abs | symbol->string |
| denominator | char-lower-case? | gcd | string->symbol |
| sqrt | char-alphabetic? | lcm | string->list |
| expt | char-numeric? | 1+ | list->string |
| ceiling | char-alphanumeric? | 1- | char->integer |
| floor | char-whitespace? | list | integer->char |
| truncate | string-copy | list-ref | caar |
| round | string-append | null? | cadr |
| exp | load | sum | cdar |
| log | file-exists? | product | cddr |
| sin | delete-file | map | caaar |
| cos | system* | filter | caadr |
| tan | get-environment-variable | reverse | cadar |
| asin | get-environment-variables | length | caddr |
| acos | open-binary-input-file | max | cdaar |
| atan | open-binary-output-file | min | cdadr |
| number->string | open-input-file | list-tail | cddar |
| string->number | open-output-file | list-head | cdddr |
| id | read | list-ref | caaaar |
| curry | read-u8 | memq | caaadr |
| foldr | read-line | memv | caadar |
| foldl | read-char | member | caaddr |
| unfold | read-all | assq | cadaar |
| reduce | write | assv | cadadr |
| call-with-input-file | display | assoc | caddar |
| call-with-output-file | newline | char=? | cadddr |
| println | write-string | char<? | cdaaar |
| compose | close-port | char>? | cdaadr |
List may not be complete.