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 1548008755920
Run it using cargo:
cd scheme.rs
cargo run
This 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-continuation
and 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.