Skip to content

hrs/blueprint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Blueprint Build Status Coverage Status

A simple little Scheme-derived language implemented in Ruby.

Blueprint is still tiny, missing a ton of functionality, and has absolutely atrocious performance. This is all just for fun.

To fire up a REPL:

$ bin/run_repl
> (+ 1 2 3)
6
>

(Consider using rlwrap for readline functionality--use rlwrap bin/run_repl)

Features

Blueprint supports a lot of the functionality you'd expect from a Scheme (though some of its syntax is a bit different):

reading and evaling:

(read "(+ 1 2 3)") # => '(+ 1 2 3)
(eval '(+ 1 2 3)) # => 6

Recursion:

(define (fact n)
  (if (== n 0)
    1
    (* n (fact (- n 1)))))

(fact 6) # => 72

Lexical closures:

(define (make-counter)
  (let ((n 0))
    (lambda ()
      (set! n (+ 1 n)))))
(define a (make-counter))
(define b (make-counter))
(a) # => 1
(a) # => 2
(b) # => 1

Variadic binding:

(define (drop-two (a b . rest)
  rest))

(drop-two 1 2 3 4 5 6) # => '(3 4 5 6)

Blueprint is completely dynamic; it does everything at runtime. As such, it doesn't have a separate macro-expansion phase and uses fexprs to handle forms where the evaluation of arguments needs to be delayed. Fexprs are non-hygienic (like Common Lisp's macros). Blueprint also emulates Common Lisp-style macros by supporting quasiquoting with backticks, commas, and ,@ for splicing, which makes writing fexprs convenient:

(deffexpr (unless condition consequent alternative)
  `(if (not ,condition)
       ,consequent
       ,alternative))

Blueprint doesn't yet have a gensym facility, though, so watch out for variable capture! That should be coming shortly.

One of Blueprint's goals is to make everything applyable, including fexprs:

(deffexpr (adder x)
  `(+ 1 ,x))

(map adder '(1 2 3)) # => '(2 3 4)

Even special forms like first, load, and quote are first-class, applicable objects:

(map first '((1 2) (3 4))) # => '(1 3)

Blueprint has a standard library that defines some basic functions and fexprs, including let, let*, if, map, reduce, filter, concatenate, and more.

Tests

Blueprint's test coverage is pretty good. The tests for the interpreter are written in RSpec, while the tests for the standard library are written in Blueprint itself.

To run all of the tests:

$ rake

About

A teeny tiny Scheme implemented in Ruby.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages