aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-10 20:34:29 -0500
committerJoel Martin <github@martintribe.org>2014-04-10 20:34:29 -0500
commitf705f0fce151863091ad77753105f0d15270edec (patch)
tree788691596846567abec1606131c972d24211604c
parent712af9efbe15a9a65c25ab92ee2a49c8e749ed3d (diff)
downloadmal-f705f0fce151863091ad77753105f0d15270edec.tar.gz
mal-f705f0fce151863091ad77753105f0d15270edec.zip
Ruby: step0, step1
-rw-r--r--Makefile13
-rw-r--r--ruby/printer.rb23
-rw-r--r--ruby/reader.rb74
-rw-r--r--ruby/step0_repl.rb25
-rw-r--r--ruby/step1_read_print.rb32
-rw-r--r--ruby/types.rb5
6 files changed, 166 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index b7feb01..8a4a6a5 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ MAL_IMPL = js
# Settings
#
-IMPLS = bash c clojure cs java js make php python ps mal
+IMPLS = bash c clojure cs java js make mal php ps python ruby
step0 = step0_repl
step1 = step1_read_print
@@ -37,24 +37,25 @@ cs_STEP_TO_PROG = cs/$($(1)).exe
java_STEP_TO_PROG = java/src/main/java/mal/$($(1)).java
js_STEP_TO_PROG = js/$($(1)).js
make_STEP_TO_PROG = make/$($(1)).mk
+mal_STEP_TO_PROG = mal/$($(1)).mal
php_STEP_TO_PROG = php/$($(1)).php
-python_STEP_TO_PROG = python/$($(1)).py
ps_STEP_TO_PROG = ps/$($(1)).ps
-mal_STEP_TO_PROG = mal/$($(1)).mal
+python_STEP_TO_PROG = python/$($(1)).py
+ruby_STEP_TO_PROG = ruby/$($(1)).rb
bash_RUNTEST = ../runtest.py $(4) ../$(1) -- bash ../$(2) $(5)
c_RUNTEST = ../runtest.py $(4) ../$(1) -- ../$(2) $(5)
clojure_RUNTEST = ../runtest.py $(4) ../$(1) -- lein with-profile +$(3) trampoline run $(5)
cs_RUNTEST = ../runtest.py --redirect $(4) ../$(1) -- mono --debug ../$(2) --raw $(5)
-#cs_RUNTEST = ../runtest.py --redirect $(4) ../$(1) -- mono --debug ../$(2) $(5)
java_RUNTEST = ../runtest.py $(4) ../$(1) -- mvn -quiet exec:java -Dexec.mainClass="mal.$($(3))" -Dexec.args="--raw$(if $(5), $(5),)"
js_RUNTEST = ../runtest.py $(4) ../$(1) -- node ../$(2) $(5)
make_RUNTEST = ../runtest.py $(4) ../$(1) -- make -f ../$(2) $(5)
+mal_RUNTEST = $(call $(MAL_IMPL)_RUNTEST,$(1),$(call $(MAL_IMPL)_STEP_TO_PROG,stepA),stepA,--start-timeout 30 --test-timeout 120,../$(2))
php_RUNTEST = ../runtest.py $(4) ../$(1) -- php ../$(2) $(5)
-python_RUNTEST = ../runtest.py $(4) ../$(1) -- python ../$(2) $(5)
ps_RUNTEST = ../runtest.py $(4) ../$(1) -- gs -q -dNODISPLAY ../$(2) $(5)
-mal_RUNTEST = $(call $(MAL_IMPL)_RUNTEST,$(1),$(call $(MAL_IMPL)_STEP_TO_PROG,stepA),stepA,--start-timeout 30 --test-timeout 120,../$(2))
+python_RUNTEST = ../runtest.py $(4) ../$(1) -- python ../$(2) $(5)
+ruby_RUNTEST = ../runtest.py $(4) ../$(1) -- ruby ../$(2) $(5)
# Derived lists
diff --git a/ruby/printer.rb b/ruby/printer.rb
new file mode 100644
index 0000000..2d46e07
--- /dev/null
+++ b/ruby/printer.rb
@@ -0,0 +1,23 @@
+require "types"
+
+def _pr_str(obj, print_readably=true)
+ _r = print_readably
+ return case obj
+ when List
+ "(" + obj.map{|x| _pr_str(x, _r)}.join(" ") + ")"
+ when Vector
+ "[" + obj.map{|x| _pr_str(x, _r)}.join(" ") + "]"
+ when String
+ if _r
+ "\"" + obj.gsub(/\\/, "\\\\") \
+ .gsub(/"/, "\\\\\"") \
+ .gsub(/\n/, "\\\\n") + "\""
+ else
+ obj
+ end
+ when nil
+ "nil"
+ else
+ obj.to_s
+ end
+end
diff --git a/ruby/reader.rb b/ruby/reader.rb
new file mode 100644
index 0000000..d224e9c
--- /dev/null
+++ b/ruby/reader.rb
@@ -0,0 +1,74 @@
+require "types"
+
+class Reader
+ def initialize(tokens)
+ @position = 0
+ @tokens = tokens
+ end
+ def peek
+ return @tokens[@position]
+ end
+ def next
+ @position += 1
+ return @tokens[@position-1]
+ end
+end
+
+
+def tokenize(str)
+ re = /[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/
+ return str.scan(re).map{|m| m[0]}.select{|m| m != ""}
+end
+
+def parse_str(t)
+ return t[1..-2].gsub(/\\"/, "\"").gsub(/\\n/, "\n")
+end
+
+def read_atom(rdr)
+ token = rdr.next
+ return case token
+ when /^-?[0-9]+$/ then token.to_i # integer
+ when /^-?[0-9][0-9.]*$/ then token.to_f # float
+ when /^"/ then parse_str(token) # string
+ when "nil" then nil
+ when "true" then true
+ when "false" then false
+ else token.to_sym # symbol
+ end
+end
+
+def read_list(rdr, klass, start="(", last =")")
+ ast = klass.new
+ token = rdr.next()
+ if token != start
+ raise "expected '" + start + "'"
+ end
+ while (token = rdr.peek) != last
+ if not token
+ raise "expected '" + last + "', got EOF"
+ end
+ ast.push(read_form(rdr))
+ end
+ rdr.next
+ return ast
+end
+
+def read_form(rdr)
+ token = rdr.peek
+ return case rdr.peek
+ when ";" then nil
+ when "(" then read_list(rdr, List, "(", ")")
+ when ")" then raise "unexpected ')'"
+ when "[" then read_list(rdr, Vector, "[", "]")
+ when "]" then raise "unexpected ']'"
+ when "{" then raise "unexpected '{'"
+ when "}" then raise "unexpected '}'"
+ else read_atom(rdr)
+ end
+end
+
+def read_str(str)
+ tokens = tokenize(str)
+ return read_form(Reader.new(tokens))
+end
+
diff --git a/ruby/step0_repl.rb b/ruby/step0_repl.rb
new file mode 100644
index 0000000..dd32b27
--- /dev/null
+++ b/ruby/step0_repl.rb
@@ -0,0 +1,25 @@
+require "readline"
+
+# read
+def READ(str)
+ return str
+end
+
+# eval
+def EVAL(ast, env)
+ return ast
+end
+
+# print
+def PRINT(exp)
+ return exp
+end
+
+# repl
+def REP(str)
+ return PRINT(EVAL(READ(str), {}))
+end
+
+while line = Readline.readline("user> ", true)
+ puts REP(line)
+end
diff --git a/ruby/step1_read_print.rb b/ruby/step1_read_print.rb
new file mode 100644
index 0000000..20dd450
--- /dev/null
+++ b/ruby/step1_read_print.rb
@@ -0,0 +1,32 @@
+require "readline"
+require "types"
+require "reader"
+require "printer"
+
+# read
+def READ(str)
+ return read_str(str)
+end
+
+# eval
+def EVAL(ast, env)
+ return ast
+end
+
+# print
+def PRINT(exp)
+ return _pr_str(exp, true)
+end
+
+# repl
+def REP(str)
+ return PRINT(EVAL(READ(str), {}))
+end
+
+while line = Readline.readline("user> ", true)
+ begin
+ puts REP(line)
+ rescue Exception => e
+ puts "Error: %{e}"
+ end
+end
diff --git a/ruby/types.rb b/ruby/types.rb
new file mode 100644
index 0000000..a7ce285
--- /dev/null
+++ b/ruby/types.rb
@@ -0,0 +1,5 @@
+class List < Array
+end
+
+class Vector < Array
+end