Skip to content

Commit

Permalink
Merge pull request #21 from noprompt/set
Browse files Browse the repository at this point in the history
Basic reading, printing, and context handling of sets
  • Loading branch information
Arlen Christian Mart Cuss committed Dec 15, 2012
2 parents 3b110ea + 363ffe1 commit cc65fc5
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 15 deletions.
1 change: 1 addition & 0 deletions lib/rouge.rb
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions lib/rouge/context.rb
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions lib/rouge/printer.rb
Expand Up @@ -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
Expand Down
43 changes: 30 additions & 13 deletions lib/rouge/reader.rb
Expand Up @@ -16,7 +16,6 @@ def initialize(ns, input)
@gensyms = []
end


def lex
r =
case peek
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand Down
4 changes: 4 additions & 0 deletions lib/rouge/seq.rb
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion 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.
Expand Down
26 changes: 26 additions & 0 deletions spec/reader_spec.rb
Expand Up @@ -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],
Expand Down
26 changes: 25 additions & 1 deletion spec/seq_spec.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit cc65fc5

Please sign in to comment.