Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #21 from noprompt/set

Basic reading, printing, and context handling of sets
  • Loading branch information...
commit cc65fc5167e05043a05ed2b41e08b4aa56cac194 2 parents 3b110ea + 363ffe1
@kivikakk kivikakk authored
View
1  lib/rouge.rb
@@ -18,6 +18,7 @@ module Rouge
require 'rouge/printer'
require 'rouge/context'
require 'rouge/repl'
+ require 'set'
def self.print(form, out)
Rouge::Printer.print form, out
View
12 lib/rouge/context.rb
@@ -210,6 +210,18 @@ def eval_call(fun, args, block)
raise ArgumentError,
"Wrong number of args (#{num_args}) passed to ruby/Hash"
end
+ when Set
+ if num_args == 1
+ el = args[0]
+ if fun.include? el
+ el
+ else
+ nil
+ end
+ else
+ raise ArgumentError,
+ "Wrong number of args (#{num_args}) passed to ruby/Set"
+ end
else
fun.call(*args, &block)
end
View
7 lib/rouge/printer.rb
@@ -53,6 +53,13 @@ def self.print(form, out)
print(kv[1], out)
end
out << "}"
+ when Set
+ out << "\#{"
+ form.each_with_index do |el, i|
+ print el, out
+ out << " " unless i == (form.size - 1)
+ end
+ out << "}"
when NilClass
out << "nil"
when TrueClass
View
43 lib/rouge/reader.rb
@@ -16,7 +16,6 @@ def initialize(ns, input)
@gensyms = []
end
-
def lex
r =
case peek
@@ -247,32 +246,47 @@ def dequote form
end
def regexp
- s = ""
- t = '"'
+ expression = ""
+ terminator = '"'
+
while true
- c = @src[@n]
+ char = @src[@n]
- if c.nil?
- reader_raise EndOfDataError, "in regexp, got: #{s}"
+ if char.nil?
+ reader_raise EndOfDataError, "in regexp, got: #{expression}"
end
@n += 1
- if c == t
+ if char == terminator
break
end
- if c == ?\\
- c = "\\"
- if peek == ?"
- c << consume
+ if char == ?\\
+ char = "\\"
+
+ # Prevent breaking early.
+ if peek == terminator
+ char << consume
end
end
- s << c
+ expression << char
end
- Regexp.new(s).freeze
+ Regexp.new(expression).freeze
+ end
+
+ def set
+ s = Set.new
+
+ until peek == '}'
+ el = lex
+ s.add el
+ end
+
+ consume
+ s.freeze
end
def dispatch
@@ -284,6 +298,9 @@ def dispatch
Rouge::Symbol[:fn],
(1..count).map {|n| Rouge::Symbol[:"%#{n}"]}.freeze,
body]
+ when "{"
+ consume
+ set
when "'"
consume
Rouge::Seq::Cons[Rouge::Symbol[:var], lex]
View
4 lib/rouge/seq.rb
@@ -264,6 +264,10 @@ def self.seq(form)
seq(form.to_a)
when String
seq(form.chars)
+ when Set
+ seq(form.to_a)
+ when Hash
+ seq(form.to_a)
else
raise UnknownSeqError, form.inspect
end
View
1  misc/TODO
@@ -1,5 +1,4 @@
NEXT:
-- (count "xyz") => 3, (map … "xyz") etc.
- (ruby/)Time/now ==> Time.now
- continue decruft Context, shift tests to Compiler as appropriate; revise most
specs.
View
26 spec/reader_spec.rb
@@ -175,6 +175,32 @@
end
end
+ describe "sets" do
+ context "the empty set" do
+ it { @ns.read('#{}').should eq Set.new }
+ end
+
+ context "multiple-element sets" do
+ it { @ns.read('#{1 2 3}').should eq Set.new.add(1).add(2).add(3) }
+ it { @ns.read('#{true () [] "no"}').
+ should eq Set.new([Rouge::Symbol[:true],
+ Rouge::Seq::Cons[],
+ [],
+ "no"]) }
+ end
+
+ context "nested sets" do
+ it { @ns.read('#{#{1} #{2} #{3}}').
+ should eq Set.new([Set.new([1]), Set.new([2]), Set.new([3])]) }
+ end
+
+ context "read as frozen" do
+ it { @ns.read('#{}').should be_frozen }
+ it { @ns.read('#{1}').should be_frozen }
+ it { @ns.read('#{1 2}').should be_frozen }
+ end
+ end
+
describe "quotations" do
it { @ns.read("'x").
should eq Rouge::Seq::Cons[Rouge::Symbol[:quote],
View
26 spec/seq_spec.rb
@@ -13,7 +13,7 @@ def to_a; [:q]; end
describe "#seq" do
it "should return the original object" do
seq.seq.should be seq
- end
+ end
end
describe "the unimplemented methods" do
@@ -196,6 +196,30 @@ def to_a; [:q]; end
let(:arrayseq) { Rouge::Seq::Array.new([:a], 0) }
it { Rouge::Seq.seq(arrayseq).should be arrayseq }
end
+
+ context Set do
+ subject { Rouge::Seq.seq(Set.new([1, 2, 3])) }
+ it { should be_an_instance_of Rouge::Seq::Array }
+ it { should eq Rouge::Seq::Array.new([1, 2, 3], 0) }
+ end
+
+ context Hash do
+ subject { Rouge::Seq.seq({:a => "a", :b => "b"}) }
+ it { should be_an_instance_of Rouge::Seq::Array }
+ it { should eq Rouge::Seq::Array.new([[:a, "a"], [:b, "b"]], 0) }
+ end
+
+ context String do
+ subject { Rouge::Seq.seq("foo") }
+ it { should be_an_instance_of Rouge::Seq::Array }
+ it { should eq Rouge::Seq::Array.new(['f', 'o', 'o'], 0) }
+ end
+
+ context Enumerator do
+ subject { Rouge::Seq.seq(1.upto(3)) }
+ it { should be_an_instance_of Rouge::Seq::Array }
+ it { should eq Rouge::Seq::Array.new([1, 2, 3], 0) }
+ end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.