Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/programble/apricot
Browse files Browse the repository at this point in the history
  • Loading branch information
vic committed Jul 30, 2012
2 parents ec00bcf + 523c646 commit df6ef0a
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 12 deletions.
7 changes: 3 additions & 4 deletions lib/apricot/namespace.rb
Expand Up @@ -35,17 +35,16 @@ def get_var(name)
Core = Namespace.new
Core.set_var(:"*ns*", Core)
Core.set_var(:"in-ns", lambda do |constant|
ns = Namespace.find_or_create constant
Apricot.current_namespace = ns
Apricot.current_namespace = Namespace.find_or_create constant
end)

class << self
def current_namespace
Core.get_var(:"*ns*")
end

def current_namespace=(mod)
Core.set_var(:"*ns*", mod)
def current_namespace=(ns)
Core.set_var(:"*ns*", ns)
end
end
end
2 changes: 1 addition & 1 deletion lib/apricot/repl.rb
Expand Up @@ -33,7 +33,7 @@ class REPL

COMPLETIONS = (COMMANDS.keys + SpecialForm::Specials.keys.map(&:to_s)).sort

def initialize(prompt, bytecode = false, history_file = nil)
def initialize(prompt = 'apr> ', bytecode = false, history_file = nil)
@prompt = prompt
@bytecode = bytecode
@history_file = File.expand_path(history_file || HISTORY_FILE)
Expand Down
29 changes: 22 additions & 7 deletions lib/apricot/special_forms.rb
Expand Up @@ -308,7 +308,7 @@ def self.let(g, args, type)
g.send_with_block :lambda, 0
end

# (try body* (rescue condition name body*)* (ensure body*)?)
# (try body* (rescue name|[name condition*] body*)* (ensure body*)?)
SpecialForm.define(:try) do |g, args|
body = []
rescue_clauses = []
Expand Down Expand Up @@ -359,16 +359,31 @@ def self.let(g, args, type)
g.push_current_exception

rescue_clauses.each do |clause|
condition, name = clause.shift(2)
# Parse either (rescue e body) or (rescue [e Exception] body)
if clause[0].is_a?(AST::Identifier)
name = clause.shift
conditions = []
elsif clause[0].is_a?(AST::ArrayLiteral)
conditions = clause.shift.elements
name = conditions.shift
raise TypeError, "Expected identifier as first form of rescue clause binding" unless name.is_a?(AST::Identifier)
else
raise TypeError, "Expected identifier or array as first form of rescue clause"
end

# Default to StandardError for (rescue e body) and (rescue [e] body)
conditions << AST::Constant.new(name.line, [:StandardError]) if conditions.empty?

body = g.new_label
next_rescue = g.new_label

g.dup # The exception
condition.bytecode(g)
g.swap
g.send :===, 1
g.git body
conditions.each do |cond|
g.dup # The exception
cond.bytecode(g)
g.swap
g.send :===, 1
g.git body
end
g.goto next_rescue

# This rescue condition matched
Expand Down
64 changes: 64 additions & 0 deletions spec/compiler_spec.rb
Expand Up @@ -158,6 +158,70 @@ def apricot(code)
CODE
end

it 'compiles try forms' do
apricot(%q|(try)|).should == nil
apricot(%q|(try :foo)|).should == :foo

apricot(%q|(try :success (rescue e :rescue))|).should == :success
expect { apricot(%q|(try (. Kernel raise))|) }.to raise_error(RuntimeError)
apricot(%q|(try (. Kernel raise) (rescue e :rescue))|).should == :rescue
apricot(%q|(try (. Kernel raise) (rescue [e] :rescue))|).should == :rescue
apricot(<<-CODE).should == :rescue
(try
(. Kernel raise)
(rescue [e 1 2 RuntimeError] :rescue))
CODE
apricot(<<-CODE).should == :rescue_bar
(try
(. Kernel raise ArgumentError)
(rescue [e TypeError] :rescue_foo)
(rescue [e ArgumentError] :rescue_bar))
CODE
apricot(<<-CODE).should be_a(TypeError)
(try
(. Kernel raise TypeError)
(rescue e e))
CODE
expect { apricot(<<-CODE) }.to raise_error(TypeError)
(try
(. Kernel raise TypeError)
(rescue [e ArgumentError] :rescue))
CODE

apricot(<<-CODE).should == :rescue
(try
(try
(. Kernel raise)
(rescue e (. Kernel raise)))
(rescue e :rescue))
CODE

apricot(<<-CODE).should == []
(let [a [1]]
(try
:success
(ensure (.pop a)))
a)
CODE
apricot(<<-CODE).should == []
(let [a [1]]
(try
(. Kernel raise)
(rescue e :rescue)
(ensure (.pop a)))
a)
CODE
apricot(<<-CODE).should == []
(let [a [1]]
(try
(try
(. Kernel raise)
(ensure (.pop a)))
(rescue e :rescue))
a)
CODE
end

it 'compiles quoted forms' do
apricot(%q|'1|).should == 1
apricot(%q|'a|).should == Apricot::Identifier.intern(:a)
Expand Down

0 comments on commit df6ef0a

Please sign in to comment.