2018-07-19 13:46:51 +02:00
|
|
|
module Ruby
|
|
|
|
class ClassStatement < Statement
|
|
|
|
attr_reader :name, :super_class_name , :body
|
|
|
|
|
2019-03-06 10:21:09 +01:00
|
|
|
# init with the class name, super class name and statement body
|
|
|
|
# body must be Method or Send (See to_vool) or empty/nil (possibly not handled right)
|
2018-07-19 13:46:51 +02:00
|
|
|
def initialize( name , supe , body)
|
|
|
|
@name , @super_class_name = name , supe
|
|
|
|
case body
|
2019-03-05 19:36:40 +01:00
|
|
|
when MethodStatement , SendStatement
|
2018-07-19 13:46:51 +02:00
|
|
|
@body = Statements.new([body])
|
|
|
|
when Statements
|
|
|
|
@body = body
|
|
|
|
when nil
|
|
|
|
@body = Statements.new([])
|
|
|
|
else
|
2019-03-05 19:36:40 +01:00
|
|
|
raise "what body #{body.class}:#{body}"
|
2018-07-19 13:46:51 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-03-06 10:21:09 +01:00
|
|
|
# Create equivalent vool objects. Mostly for method statements
|
|
|
|
# For calls, call transform_statement, see there
|
2018-07-19 13:59:10 +02:00
|
|
|
def to_vool
|
2019-03-06 10:21:09 +01:00
|
|
|
meths = []
|
|
|
|
body.statements.each do |meth|
|
|
|
|
if( meth.is_a?(MethodStatement))
|
|
|
|
meths << meth.to_vool
|
|
|
|
else
|
|
|
|
meths += transform_statement(meth)
|
|
|
|
end
|
2019-03-05 19:36:40 +01:00
|
|
|
end
|
2018-07-19 20:44:48 +02:00
|
|
|
Vool::ClassStatement.new(@name , @super_class_name, Vool::Statements.new(meths) )
|
2018-07-19 13:46:51 +02:00
|
|
|
end
|
|
|
|
|
2019-03-06 10:21:09 +01:00
|
|
|
# We rewrite certain send statements (so raise error for all else)
|
|
|
|
# Currently only attributes (ie attr :name) supported, for which the standard getter
|
|
|
|
# and setter is created and returned as vool
|
|
|
|
def transform_statement( class_send )
|
2019-03-05 19:36:40 +01:00
|
|
|
unless class_send.is_a?(SendStatement)
|
|
|
|
raise "Other than methods, only class methods allowed, not #{class_send.class}"
|
|
|
|
end
|
2019-03-07 10:00:18 +01:00
|
|
|
allowed = [:attr , :attr_reader]
|
|
|
|
attr_name = class_send.name
|
|
|
|
unless allowed.include?(attr_name)
|
|
|
|
raise "Only remapping #{allowed}, not #{attr_name}"
|
2019-03-05 19:36:40 +01:00
|
|
|
end
|
2019-03-07 09:47:48 +01:00
|
|
|
methods = []
|
|
|
|
class_send.arguments.each do |attr|
|
|
|
|
methods << getter_for(attr.value)
|
2019-03-07 10:00:18 +01:00
|
|
|
methods << setter_for(attr.value) if attr_name == :attr
|
2019-03-07 09:47:48 +01:00
|
|
|
end
|
|
|
|
methods
|
2019-03-06 10:21:09 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
# creates a getter method for the given instance name (sym)
|
|
|
|
# The Method is created in Ruby, and to_vool is called to transform to Vool
|
|
|
|
# The standard getter obviously only returns the ivar
|
|
|
|
def getter_for(instance_name)
|
|
|
|
return_statement = ReturnStatement.new(InstanceVariable.new(instance_name))
|
|
|
|
MethodStatement.new(instance_name , [] , return_statement).to_vool
|
|
|
|
end
|
|
|
|
|
|
|
|
# creates a setter method (name=) for the given instance name (sym)
|
|
|
|
# The Method is created in Ruby, and to_vool is called to transform to Vool
|
|
|
|
# The setter method assigns the incoming value and returns the ivar
|
|
|
|
def setter_for(instance_name)
|
|
|
|
assign = IvarAssignment.new(instance_name , LocalVariable.new(:val))
|
|
|
|
return_statement = ReturnStatement.new(InstanceVariable.new(instance_name))
|
|
|
|
statements = Statements.new([assign, return_statement])
|
|
|
|
MethodStatement.new("#{instance_name}=".to_sym , [:val] , statements).to_vool
|
2019-03-05 19:36:40 +01:00
|
|
|
end
|
|
|
|
|
2018-07-19 13:46:51 +02:00
|
|
|
def to_s(depth = 0)
|
|
|
|
at_depth(depth , "class #{name}" , @body.to_s(depth + 1) , "end")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|