Skip to content

a simple yet comprehensive scheme interpreter in rust

License

Notifications You must be signed in to change notification settings

isamert/scheme.rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

92 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scheme.rs

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.

Motivation

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.

Examples

;; 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

Usage

Run it using cargo:

cd scheme.rs
cargo run

This will fire up REPL. You can also run files directly:

cargo run filename.scm

Notes about implementation

Extras

  • Brackets can be used instead of parenthesis.

What is not included?

  • Mutable lists
  • Vectors (Lists are implemented in terms of vectors)
  • Hygienic macros
  • call-with-current-continuation and it’s derivatives

Proper tail recursion

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.

Goals

  • [ ] 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).

List of functions

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>?
letcondexact?char-ci<=?
let*caseinexact?char-ci>=?
letrecandnumber?string=?
quoteorpair?string<?
quasiquoteconslist?string>?
unquotecaroutput-port?string<=?
eqv?cdrinput-port?string>=?
eq?appendtextual-port?string-ci=?
equal?list-copybinary-port?string-ci<?
+string-appendnotstring-ci>?
-string-upcasezero?string-ci<=?
*string-downcasepositive?string-ci>=?
/string-lengthnegative?substring
remainderchar-upcaseodd?string-ref
modulochar-downcaseeven?string
numeratorchar-upper-case?abssymbol->string
denominatorchar-lower-case?gcdstring->symbol
sqrtchar-alphabetic?lcmstring->list
exptchar-numeric?1+list->string
ceilingchar-alphanumeric?1-char->integer
floorchar-whitespace?listinteger->char
truncatestring-copylist-refcaar
roundstring-appendnull?cadr
exploadsumcdar
logfile-exists?productcddr
sindelete-filemapcaaar
cossystem*filtercaadr
tanget-environment-variablereversecadar
asinget-environment-variableslengthcaddr
acosopen-binary-input-filemaxcdaar
atanopen-binary-output-filemincdadr
number->stringopen-input-filelist-tailcddar
string->numberopen-output-filelist-headcdddr
idreadlist-refcaaaar
curryread-u8memqcaaadr
foldrread-linememvcaadar
foldlread-charmembercaaddr
unfoldread-allassqcadaar
reducewriteassvcadadr
call-with-input-filedisplayassoccaddar
call-with-output-filenewlinechar=?cadddr
printlnwrite-stringchar<?cdaaar
composeclose-portchar>?cdaadr

List may not be complete.

About

a simple yet comprehensive scheme interpreter in rust

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages