module Melbourne
module AST
# A +case+ statement as in
#
# case
# when a == 1 then
# # something
# when a == 2
# # something
# end
#
class Case < Node
# The +when+ nodes of the +case+ statement
#
attr_accessor :whens
# The +else+ node of the +case+ statement (or +nil+ if there is none)
#
attr_accessor :else
def initialize(line, whens, else_body) #:nodoc:
@line = line
@whens = whens
@else = else_body || Nil.new(line)
end
end
# A +case+ statement with a receiver as in:
#
# case a
# when 1 then
# # something
# when 2
# # something
# end
#
class ReceiverCase < Case
# The receiver of the +case+ statement
#
attr_accessor :receiver
def initialize(line, receiver, whens, else_body) #:nodoc:
@line = line
@receiver = receiver
@whens = whens
@else = else_body || Nil.new(line)
end
end
# A +when+ statement in a +case+ statement as in:
#
# case a
# when 1 then
# # something
# when 2
# # something
# end
#
class When < Node
# The conditions for which the +when+ statement is true or +nil+ if only a single value is specified
#
attr_accessor :conditions
# The body for the +when+ statement
#
attr_accessor :body
# The single value for the +when+ statement if only a single value is specified, +nil+ otherwise
#
attr_accessor :single
# Any splat (*something) that is specified as a condition for the +when+ statement or +nil+ of no splat is specified
#
attr_accessor :splat
def initialize(line, conditions, body) #:nodoc:
@line = line
@body = body || Nil.new(line)
@splat = nil
@single = nil
if conditions.kind_of? ArrayLiteral
if conditions.body.last.kind_of? When
last = conditions.body.pop
if last.conditions.kind_of? ArrayLiteral
conditions.body.concat last.conditions.body
elsif last.single
@splat = SplatWhen.new line, last.single
else
@splat = SplatWhen.new line, last.conditions
end
end
if conditions.body.size == 1 and !@splat
@single = conditions.body.first
else
@conditions = conditions
end
else
@conditions = conditions
end
end
end
# A splat (*something) inside a condition of a +when+ statement as in:
#
# case a
# when *c then
# d
# end
#
class SplatWhen < Node
# The actual content of the plat
#
attr_accessor :condition
def initialize(line, condition) #:nodoc:
@line = line
@condition = condition
end
end
# A flip statement as in:
#
# 1 if TRUE..FALSE
#
class Flip2 < Node
def initialize(line, start, finish) #:nodoc:
@line = line
@start = start
@finish = finish
end
end
# An end-exclusive flip statement as in:
#
# 1 if TRUE...FALSE
#
class Flip3 < Node
def initialize(line, start, finish) #:nodoc:
@line = line
@start = start
@finish = finish
end
end
# An +if+ statement as in:
#
# a if true
#
class If < Node
# The condition of the +if+ statement
#
attr_accessor :condition
# The body of the +if+ statement (the code that is executed if the +condition+ evaluates to true)
#
attr_accessor :body
# The +else+ block of the +if+ statement (if there is one)
#
attr_accessor :else
def initialize(line, condition, body, else_body) #:nodoc:
@line = line
@condition = condition
@body = body || Nil.new(line)
@else = else_body || Nil.new(line)
end
end
# A +while+ statement as in:
#
# i += 1 while go_on?
#
class While < Node
# The condition of the +while+ statement
#
attr_accessor :condition
# The body of the +while+ statement (the code that is executed if the +condition+ evaluates to true)
#
attr_accessor :body
# Whether to check the +while+ statement's condition before or after ths code in the +body+ is executed
#
attr_accessor :check_first
def initialize(line, condition, body, check_first) #:nodoc:
@line = line
@condition = condition
@body = body || Nil.new(line)
@check_first = check_first
end
end
# An +until+ statement as in:
#
# i += 1 until stop?
#
class Until < While
end
# A regular expression match statement as in:
#
# x =~ /x/
#
class Match < Node
# the regex pattern used for the match
#
attr_accessor :pattern
def initialize(line, pattern, flags) #:nodoc:
@line = line
@pattern = RegexLiteral.new line, pattern, flags
end
end
# A regular expression match statement with the regular expression pattern as the receiver as in:
#
# /x/ =~ x
#
class Match2 < Node
# the regex pattern used for the match
#
attr_accessor :pattern
# the value that is matched against the +pattern+
#
attr_accessor :value
def initialize(line, pattern, value) #:nodoc:
@line = line
@pattern = pattern
@value = value
end
end
# A regular expression match statement where a String is matched against the pattern as in:
#
# 'some' =~ /x/
#
class Match3 < Node
# the regex pattern used for the match
#
attr_accessor :pattern
# the value that is matched against the +pattern+
#
attr_accessor :value
def initialize(line, pattern, value) #:nodoc:
@line = line
@pattern = pattern
@value = value
end
end
# A +break+ statement as in:
#
# while true do
# begin
# x
# rescue Exception => x
# break
# end
# end
#
class Break < Node
# The value passed to +break+
#
attr_accessor :value
def initialize(line, expr) #:nodoc:
@line = line
@value = expr || Nil.new(line)
end
end
# A +next+ statement as in:
#
# while true do
# next if skip?(i)
# i += 1
# end
#
class Next < Break
def initialize(line, value) #:nodoc:
@line = line
@value = value
end
end
# A +redo+ statement as in:
#
# while true do
# begin
# x
# rescue Exception => x
# redo
# end
# end
#
class Redo < Break
def initialize(line) #:nodoc:
@line = line
end
end
# A +redo+ statement as in:
#
# while true do
# begin
# x
# rescue Exception => x
# try_to_fix()
# retry
# end
# end
#
class Retry < Break
def initialize(line) #:nodoc:
@line = line
end
end
# A +return+ statement as in:
#
# def method
# return 3
# end
#
class Return < Node
# The value passed to +return+
#
attr_accessor :value
def initialize(line, expr) #:nodoc:
@line = line
@value = expr
@splat = nil
end
end
end
end