diff options
| author | Joel Martin <github@martintribe.org> | 2015-03-02 21:33:10 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-03-02 21:33:10 -0600 |
| commit | 835fb7d8b06e2b44792a97ac89994658bf6d00af (patch) | |
| tree | 578f67726ab9e3ce5fcbc50220e9761a66c5ddf1 /ruby | |
| parent | 6b72e6078a7d505ecf9d711eb4a16fc4dfac36b6 (diff) | |
| parent | 8a98ef9a3f3a6b6d05d02dc305a0c886c907e0f3 (diff) | |
| download | mal-835fb7d8b06e2b44792a97ac89994658bf6d00af.tar.gz mal-835fb7d8b06e2b44792a97ac89994658bf6d00af.zip | |
Merge branch 'master' into gh-pages
Conflicts:
.gitignore
Diffstat (limited to 'ruby')
| -rw-r--r-- | ruby/Makefile | 2 | ||||
| -rw-r--r-- | ruby/core.rb | 12 | ||||
| -rw-r--r-- | ruby/mal_readline.rb | 2 | ||||
| -rw-r--r-- | ruby/printer.rb | 6 | ||||
| -rw-r--r-- | ruby/reader.rb | 6 | ||||
| -rw-r--r-- | ruby/step0_repl.rb | 3 | ||||
| -rw-r--r-- | ruby/step1_read_print.rb | 9 | ||||
| -rw-r--r-- | ruby/step2_eval.rb | 9 | ||||
| -rw-r--r-- | ruby/step3_env.rb | 11 | ||||
| -rw-r--r-- | ruby/step4_if_fn_do.rb | 13 | ||||
| -rw-r--r-- | ruby/step5_tco.rb | 13 | ||||
| -rw-r--r-- | ruby/step6_file.rb | 13 | ||||
| -rw-r--r-- | ruby/step7_quote.rb | 13 | ||||
| -rw-r--r-- | ruby/step8_macros.rb | 13 | ||||
| -rw-r--r-- | ruby/step9_try.rb (renamed from ruby/step9_interop.rb) | 30 | ||||
| -rw-r--r-- | ruby/stepA_mal.rb (renamed from ruby/stepA_more.rb) | 19 | ||||
| -rw-r--r-- | ruby/tests/stepA_mal.mal | 27 | ||||
| -rw-r--r-- | ruby/types.rb | 2 |
18 files changed, 120 insertions, 83 deletions
diff --git a/ruby/Makefile b/ruby/Makefile index 71ab92c..2241a4e 100644 --- a/ruby/Makefile +++ b/ruby/Makefile @@ -1,7 +1,7 @@ TESTS = SOURCES_BASE = mal_readline.rb types.rb reader.rb printer.rb -SOURCES_LISP = env.rb core.rb stepA_more.rb +SOURCES_LISP = env.rb core.rb stepA_mal.rb SOURCES = $(SOURCES_BASE) $(SOURCES_LISP) #all: mal.rb diff --git a/ruby/core.rb b/ruby/core.rb index 6b127ba..b82bddc 100644 --- a/ruby/core.rb +++ b/ruby/core.rb @@ -1,6 +1,6 @@ require "readline" -require "reader" -require "printer" +require_relative "reader" +require_relative "printer" $core_ns = { :"=" => lambda {|a,b| a == b}, @@ -8,8 +8,10 @@ $core_ns = { :nil? => lambda {|a| a == nil}, :true? => lambda {|a| a == true}, :false? => lambda {|a| a == false}, + :symbol => lambda {|a| a.to_sym}, :symbol? => lambda {|a| a.is_a? Symbol}, - :symbol? => lambda {|a| a.is_a? Symbol}, + :keyword => lambda {|a| "\u029e"+a}, + :keyword? => lambda {|a| (a.is_a? String) && "\u029e" == a[0]}, :"pr-str" => lambda {|*a| a.map {|e| _pr_str(e, true)}.join(" ")}, :str => lambda {|*a| a.map {|e| _pr_str(e, false)}.join("")}, @@ -44,11 +46,11 @@ $core_ns = { :sequential? => lambda {|a| sequential?(a)}, :cons => lambda {|a,b| List.new(b.clone.insert(0,a))}, :concat => lambda {|*a| List.new(a && a.reduce(:concat) || [])}, - :nth => lambda {|a,b| a[b]}, + :nth => lambda {|a,b| raise "nth: index out of range" if b >= a.size; a[b]}, :first => lambda {|a| a[0]}, :rest => lambda {|a| List.new(a.size > 0 && a.drop(1) || [])}, :empty? => lambda {|a| a.size == 0}, - :count => lambda {|a| a.size}, + :count => lambda {|a| return 0 if a == nil; a.size}, :conj => lambda {|*a| a[0].clone.conj(a.drop(1))}, :apply => lambda {|*a| a[0][*a[1..-2].concat(a[-1])]}, :map => lambda {|a,b| List.new(b.map {|e| a[e]})}, diff --git a/ruby/mal_readline.rb b/ruby/mal_readline.rb index 63c5571..3799783 100644 --- a/ruby/mal_readline.rb +++ b/ruby/mal_readline.rb @@ -4,7 +4,7 @@ $history_loaded = false $histfile = "#{ENV['HOME']}/.mal-history" def _readline(prompt) - if not $history_loaded + if !$history_loaded && File.exist?($histfile) $history_loaded = true File.readlines($histfile).each {|l| Readline::HISTORY.push(l.chomp)} end diff --git a/ruby/printer.rb b/ruby/printer.rb index cfcd064..ef067a5 100644 --- a/ruby/printer.rb +++ b/ruby/printer.rb @@ -1,4 +1,4 @@ -require "types" +require_relative "types" def _pr_str(obj, print_readably=true) _r = print_readably @@ -12,7 +12,9 @@ def _pr_str(obj, print_readably=true) obj.each{|k,v| ret.push(_pr_str(k,_r), _pr_str(v,_r))} "{" + ret.join(" ") + "}" when String - if _r + if obj[0] == "\u029e" + ":" + obj[1..-1] + elsif _r obj.inspect # escape special characters else obj diff --git a/ruby/reader.rb b/ruby/reader.rb index 1039105..badc6ec 100644 --- a/ruby/reader.rb +++ b/ruby/reader.rb @@ -1,4 +1,4 @@ -require "types" +require_relative "types" class Reader def initialize(tokens) @@ -31,7 +31,8 @@ def read_atom(rdr) 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 /^".*"$/ then parse_str(token) # string + when /^:/ then "\u029e" + token[1..-1] # keyword when "nil" then nil when "true" then true when "false" then false @@ -56,7 +57,6 @@ def read_list(rdr, klass, start="(", last =")") end def read_form(rdr) - token = rdr.peek return case rdr.peek when ";" then nil when "'" then rdr.next; List.new [:quote, read_form(rdr)] diff --git a/ruby/step0_repl.rb b/ruby/step0_repl.rb index 9c03cfa..2f9e6a9 100644 --- a/ruby/step0_repl.rb +++ b/ruby/step0_repl.rb @@ -1,5 +1,4 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" +require_relative "mal_readline" # read def READ(str) diff --git a/ruby/step1_read_print.rb b/ruby/step1_read_print.rb index ded992a..ef416c3 100644 --- a/ruby/step1_read_print.rb +++ b/ruby/step1_read_print.rb @@ -1,8 +1,7 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" # read def READ(str) diff --git a/ruby/step2_eval.rb b/ruby/step2_eval.rb index 50a135d..d2b7e1a 100644 --- a/ruby/step2_eval.rb +++ b/ruby/step2_eval.rb @@ -1,8 +1,7 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" # read def READ(str) diff --git a/ruby/step3_env.rb b/ruby/step3_env.rb index 17126c5..ec8405b 100644 --- a/ruby/step3_env.rb +++ b/ruby/step3_env.rb @@ -1,9 +1,8 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" # read def READ(str) diff --git a/ruby/step4_if_fn_do.rb b/ruby/step4_if_fn_do.rb index a93463b..151ecf6 100644 --- a/ruby/step4_if_fn_do.rb +++ b/ruby/step4_if_fn_do.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) diff --git a/ruby/step5_tco.rb b/ruby/step5_tco.rb index 38bb204..80be457 100644 --- a/ruby/step5_tco.rb +++ b/ruby/step5_tco.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) diff --git a/ruby/step6_file.rb b/ruby/step6_file.rb index 0c99cee..4eeca86 100644 --- a/ruby/step6_file.rb +++ b/ruby/step6_file.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) diff --git a/ruby/step7_quote.rb b/ruby/step7_quote.rb index 48385f1..23d9499 100644 --- a/ruby/step7_quote.rb +++ b/ruby/step7_quote.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) diff --git a/ruby/step8_macros.rb b/ruby/step8_macros.rb index 58adaea..488db12 100644 --- a/ruby/step8_macros.rb +++ b/ruby/step8_macros.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) diff --git a/ruby/step9_interop.rb b/ruby/step9_try.rb index 6d2cbe2..533853b 100644 --- a/ruby/step9_interop.rb +++ b/ruby/step9_try.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) @@ -95,8 +94,21 @@ def EVAL(ast, env) return env.set(a1, func) when :macroexpand return macroexpand(a1, env) - when :"rb*" - return eval(a1) + when :"try*" + begin + return EVAL(a1, env) + rescue Exception => exc + if exc.is_a? MalException + exc = exc.data + else + exc = exc.message + end + if a2 && a2[0] == :"catch*" + return EVAL(a2[2], Env.new(env, [a2[1]], [exc])) + else + raise esc + end + end when :do eval_ast(ast[1..-2], env) ast = ast.last # Continue loop (TCO) diff --git a/ruby/stepA_more.rb b/ruby/stepA_mal.rb index 6123293..115fc8a 100644 --- a/ruby/stepA_more.rb +++ b/ruby/stepA_mal.rb @@ -1,10 +1,9 @@ -$: << File.expand_path(File.dirname(__FILE__)) -require "mal_readline" -require "types" -require "reader" -require "printer" -require "env" -require "core" +require_relative "mal_readline" +require_relative "types" +require_relative "reader" +require_relative "printer" +require_relative "env" +require_relative "core" # read def READ(str) @@ -96,7 +95,11 @@ def EVAL(ast, env) when :macroexpand return macroexpand(a1, env) when :"rb*" - return eval(a1) + res = eval(a1) + return case res + when Array; List.new res + else; res + end when :"try*" begin return EVAL(a1, env) diff --git a/ruby/tests/stepA_mal.mal b/ruby/tests/stepA_mal.mal new file mode 100644 index 0000000..2d7efb8 --- /dev/null +++ b/ruby/tests/stepA_mal.mal @@ -0,0 +1,27 @@ +;; Testing basic ruby interop + +(rb* "7") +;=>7 + +(rb* "'7'") +;=>"7" + +(rb* "[7,8,9]") +;=>(7 8 9) + +(rb* "{\"abc\" => 789}") +;=>{"abc" 789} + +(rb* "print 'hello\n'") +; hello +;=>nil + +(rb* "$foo=8;") +(rb* "$foo") +;=>8 + +(rb* "['a','b','c'].map{|x| 'X'+x+'Y'}.join(' ')") +;=>"XaY XbY XcY" + +(rb* "[1,2,3].map{|x| 1+x}") +;=>(2 3 4) diff --git a/ruby/types.rb b/ruby/types.rb index 72d24d1..d64664b 100644 --- a/ruby/types.rb +++ b/ruby/types.rb @@ -1,4 +1,4 @@ -require "env" +require_relative "env" class MalException < StandardError attr_reader :data |
