Skip to content

Commit

Permalink
Release
Browse files Browse the repository at this point in the history
  • Loading branch information
mewo2 committed Jan 17, 2016
0 parents commit 8474c07
Show file tree
Hide file tree
Showing 26 changed files with 1,811 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bin/
22 changes: 22 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
This code is licensed under the MIT License:

> Copyright (c) 2014-2016: Martin O'Leary
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CFILES = src/lexer.c \
src/error.c \
src/gc.c \
src/sexp.c \
src/builtins.c \
src/environment.c \
src/eval.c \
src/print.c \
src/parser.c

HFILES = $(CFILES:.c=.h)

bin/gertie: src/gertie.c $(CFILES) $(HFILES)
mkdir -p bin
clang src/gertie.c $(CFILES) -o bin/gertie -g

test: bin/gertie test.py prelude.grt
python test.py

clean:
rm -rf bin/*
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Gertie: a Lisp interpreter

This is a Lisp interpreter I developed over the course of a few weeks in 2014,
as a learning exercise. You probably don't want to use it for anything - it is
very much a product of a beginner.

The language itself is broadly Scheme-like, but not very well developed. The
type system is rudimentary, and the macros are extremely unhygienic. I got
bored before implementing `call/cc`, but all of the framework for it is there.

Some features:
* Basic lispish syntax (`lambda`, `let`, `define`, `if`, etc)
* A slightly janky macro system
* More sophisticated syntax (`let*`, `cond`, etc) defined through macros
* A mostly bootstrapped standard library
* A mark-and-sweep garbage collector
* A terrible hand-written lexer/parser
9 changes: 9 additions & 0 deletions TODO
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
To do
=====

* Escape sequences
* Better macros
* I/O
* Error handling
* Continuations

211 changes: 211 additions & 0 deletions prelude.grt
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
(define nil '())
(define car head)
(define cdr tail)
(define caar (lambda (x) (head (head x))))
(define cadr (lambda (x) (head (tail x))))
(define cdar (lambda (x) (tail (head x))))
(define cddr (lambda (x) (tail (tail x))))
(define caddr (lambda (x) (head (tail (tail x)))))
(define cons pair)
(define first head)
(define second cadr)
(define third caddr)
(define not (lambda (x) (if x #f #t)))
(define add1
(lambda (x) (+ x 1)))
(define sub1
(lambda (x) (- x 1)))
(define map
(lambda (f lst)
(if (pair? lst)
(pair
(apply f (head lst))
(map f (tail lst)))
nil
)))
(define yes (lambda (x) #t))
(define no (lambda (x) #f))
(define macro-transformers nil)
(define register-macro
(lambda (keyword test transform)
(begin
(define lst (assoc keyword macro-transformers))
(define new-entry (pair test transform))
(if lst
(fail)
(set! macro-transformers
(pair (pair keyword (list new-entry)) macro-transformers))
))))
(define apply-macro-list
(lambda (form lst)
(if (pair? lst)
(begin
(define macro (head lst))
(define others (tail lst))
(define test (head macro))
(define transform (tail macro))
(if (test form)
(transform form)
(apply-macro-list form others)))
'macro-not-found)))

(define macro-expand
(lambda (form)
(if (pair? form)
(begin
(define f (head form))
(define args (tail form))
(define macro-list (assoc f macro-transformers))
(if macro-list
(begin
(define applied (apply-macro-list form (tail macro-list)))
(if (equal? applied 'macro-not-found)
(map macro-expand form)
(macro-expand applied)))
(map macro-expand form)))
form
)))
(define expand-quasiquote
(lambda (form)
(if (pair? form)
(begin
(define kw (head form))
(if (equal? kw 'unquote)
(second form)
(begin
(define expand
(lambda (item)
(if (pair? item)
(if (equal? (head item) 'unquote)
(list 'list (second item))
(if (equal? (head item) 'unquote-splicing)
(second item)
(list 'list (expand-quasiquote item))))
(list 'list (expand-quasiquote item)))))
(pair 'append (map expand form)))))
(if (symbol? form)
(list 'quote form)
form))))
(register-macro
'quasiquote
yes
(lambda (form) (expand-quasiquote (second form))))

(register-macro
'define
(lambda (form) (pair? (second form)))
(lambda (form)
(begin
(define arglist (second form))
(define body (third form))
`(define ,(head arglist) (lambda ,(tail arglist) ,body)))))
(register-macro
'let
yes
(lambda (form)
(begin
(define arglist (second form))
(define body (third form))
(if (pair? arglist)
(begin
(define argpair (head arglist))
(define rest (tail arglist))
(define var (first argpair))
(define val (second argpair))
`(let ,rest ((lambda (,var) ,body) ,val)))
body))))

(register-macro
'or
yes
(lambda (form)
(let
((args (tail form)))
(if (pair? args)
(if (pair? (tail args))
`(if ,(head args) ,(head args) (or ,@(tail args)))
(head args))
#f))))
(register-macro
'and
yes
(lambda (form)
(let
((args (tail form)))
(if (pair? args)
(if (pair? (tail args))
`(if ,(head args) (and ,@(tail args)) #f)
(head args))
#t))))

(register-macro
'lambda
(lambda (form) (> (length form) 3))
(lambda (form)
(let
((body (cddr form)))
`(lambda (second form) (begin ,@body)))))
(register-macro
'cond
yes
(lambda (form)
(if (pair? (tail form))
(let
((first-cond (second form))
(rest-conds (cddr form)))
(let
((test (first first-cond))
(expr (second first-cond)))
(if (equal? test 'else)
expr
`(if ,test ,expr (cond ,@rest-conds)))))
#f)))
(define (in? elt lst)
(if (pair? lst)
(or
(equal? elt (head lst))
(in? elt (tail lst)))
#f))
(register-macro
'case
yes
(lambda (form)
(let ((keysym (gensym)))
(let
((key (second form))
(exprs (cddr form))
(expand-expr
(lambda (ex)
(begin
(define vals (head ex))
(define body (second ex))
(define test
(if (equal? 'else vals)
'else
`(in? ,keysym ',vals)))
`(,test ,body)))))
`(let ((,keysym ,key))
(cond ,@(map expand-expr exprs)))))))
(define (for-each proc args)
(if (pair? args)
(begin
(define res (apply proc (head args)))
(pair res (for-each proc (tail args))))
nil))
Loading

0 comments on commit 8474c07

Please sign in to comment.