hello.
thanks for visiting! I'm erik, and I'll be a junior in computer science here at cu next fall. I'm interested in most any topic in computer science, maybe especially programming languages and the theory of computation, right now.
if you'd like to contact me, send an email!
my projects.
jeme is a compiler for the scheme programming language that generates JVM bytecode. I'm bootstrapping the compiler with mzscheme, but the end goal is for it to be self-hosting. it's hosted at google code.
most recently I've been working on implementing a
syntax-rules macro system;
I've made some progress, and am currently trying to
identify and fix bugs.
here is a short example (from macros that work) of how the compiler might process some code that defines and uses a simple macro:
;; push.scm
(define-syntax push
(syntax-rules ()
((push ?v ?x)
(set! ?x (cons ?v ?x)))))
(define (main args)
(let ((pros (list "cheap" "fast"))
(cons (list)))
(push "unreliable" cons)
(display cons)
(newline)))
the
syntax
expander walks the parse tree of this code, looking for macro calls to expand.
it expands define, let, and push, and then
returns a new parse tree which it passes along to the
code
generator.
;; expanded
(define main
(lambda (_gs3_)
((lambda (_gs5_ _gs6_)
(set! _gs6_ (cons "unreliable" _gs6_))
(display _gs6_)
(newline))
(list "cheap" "fast")
(list))))
// compiled ... 62: iconst_2 63: anewarray #70; //class jeme/lang/SchemeObject 66: dup 67: iconst_0 68: new #72; //class jeme/lang/SchemeString 71: dup 72: ldc #74; //String unreliable 74: invokespecial #77; //Method jeme/lang/SchemeString."<init>" 77: aastore 78: dup 79: iconst_1 80: getstatic #56; //Field p1:Lpush; ...
at this point, because main was defined as a procedure of one argument,
we have an executable java class:
% mzscheme -t compiler.scm -m push.scm
% java push
("unreliable")
in the future, I would like to possibly try to add some sort of optimizations
(e.g., especially for self-recursive tail-calls), and continue to implement more of
the scheme language and standard library. I only plan to support escape continuations,
i.e., that just throw an Exception (and aren't first-class).
it would be really cool to have an interface to java classes (and a macro for defining them), but I'll have to think more about how to best implement this.
turing machine simulator is a pretty
trivial piece of code I wrote to model turing machines
with scheme. using it, here is how we might define a
machine that writes a 1 if its input is
odd length, and writes 0 otherwise:
(define odd-length?
'((start . 1)
((1 . a) 2 _ . R)
((2 . a) 1 _ . R)
((1 . _) 3 0 . R)
((2 . _) 3 1 . R)
(accept . 3)))
simulate runs a machine with a given input
"tape," which is just a list of symbols. so for example,
(simulate odd-length? '(a a a)) returns
(_ _ _ 1) and (simulate odd-length?
'(a a)) returns (_ _ 0).
(define (simulate machine tape)
(let ((accept (accept-state machine)))
(let loop ((state (start-state machine))
(tape (cons '() tape)))
(if (or (not state) (eq? accept state))
(append (reverse (car tape))
(cdr tape))
(let ((next (step machine state tape)))
(loop (car next) (cdr next)))))))
the procedure write-machine will write a
DOT file for a
machine, that can be used to create pictures:
I've posted the rest of the code to
tm-simulator.scm,
in case anyone is interested. as far as I know, this is
all portable R5RS except for maybe one line in
write-machine that's specific to mzscheme.
self-enumerating pangrams is a project that I've wanted to work on for while but that only now I hope to get started. The goal is to, given a prefix and a set of symbols, generate a sentence that begins with the prefix and then enumerates itself for the specified symbols.
for example, (sep "This sentence contains"
'(#\a #\b)), where sep is the
program, might return "This sentence contains
three a's and one b." as I get started, I'll
store my code in
pangrams.scm.
js-scheme is an interpreter for a small subset of the scheme programming language written in javascript. it's hosted right here, for now.
an alternate version of the interpreter is written in cps so that it can provide re-invokable continuations. this is of limited use as the javascript stack will overflow very quickly. the regular interpreter comes with "plug-ins" for last.fm and flot.
> (define (generate-one-element-at-a-time lst) .. (define (generator) .. (call/cc control-state)) .. (define (control-state return) .. (for-each .. (lambda (element) .. (set! return .. (call/cc .. (lambda (resume-here) .. (set! control-state resume-here) .. (return element))))) .. lst) .. (return 'you-fell-off-the-end)) .. generator) ;Value: generate-one-element-at-a-time > (define generate-digit .. (generate-one-element-at-a-time '(0 1 2))) ;Value: generate-digit > (generate-digit) ;Value: 0 > (generate-digit) ;Value: 1 > (generate-digit) ;Value: 2 > (generate-digit) ;Value: you-fell-off-the-end