From 2eda0f6d07ddb3cacc3a4b78728019d5de26cb90 Mon Sep 17 00:00:00 2001 From: Phil Hagelberg Date: Fri, 7 Nov 2008 22:57:05 -0800 Subject: [PATCH] Whoa; I just implemented quasiquote. That was way too easy. --- lib/bus_scheme/eval.rb | 12 ++++++++++++ lib/bus_scheme/primitives.rb | 7 ++----- test/test_eval.rb | 5 +++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/lib/bus_scheme/eval.rb b/lib/bus_scheme/eval.rb index 816d115..69f6daf 100644 --- a/lib/bus_scheme/eval.rb +++ b/lib/bus_scheme/eval.rb @@ -55,4 +55,16 @@ def stacktrace def stack @@stack end + + # TODO: unquote-splicing + def quasiquote(arg) + if !arg.is_a? Cons or arg.empty? + arg + elsif arg.is_a? Cons and arg.car == 'unquote'.sym + eval(arg.cadr) + else + Cons.new(quasiquote(arg.car), + quasiquote(arg.cdr)) + end + end end diff --git a/lib/bus_scheme/primitives.rb b/lib/bus_scheme/primitives.rb index 9357c15..c8a7e33 100644 --- a/lib/bus_scheme/primitives.rb +++ b/lib/bus_scheme/primitives.rb @@ -43,11 +43,8 @@ def self.special_form(identifier, value) define 'exit', primitive { exit } define 'quit', BusScheme['exit'.sym] - - # TODO: write - special_form 'quasiquote', primitive { } - special_form 'unquote', primitive { } - special_form 'unquote-splicing', primitive { } + special_form 'quasiquote', primitive { |arg| quasiquote(arg) } + special_form 'qq', BusScheme['quasiquote'.sym] # Primitives that can't be defined in terms of other forms: special_form 'quote', primitive { |arg| arg } diff --git a/test/test_eval.rb b/test/test_eval.rb index 0dd1bfe..ce55661 100644 --- a/test/test_eval.rb +++ b/test/test_eval.rb @@ -87,6 +87,11 @@ def test_evals_string_ending_in_comment ;; should be four" end + def test_quasi_quote + assert_evals_to([:hey.sym, :there.sym, "dude"].to_list, + '(qq (hey there (unquote (+ "du" "de"))))') + end + # def test_tail_call_optimization # Timeout.timeout(1) do # assert_nothing_raised { eval "((lambda (x) (x x)) (lambda (x) (x x)))" }