base/maroon_base.rb in maroon-0.6.5 vs base/maroon_base.rb in maroon-0.7.0
- old
+ new
@@ -17,251 +17,293 @@
# say do
# @who #could be self as well to refer to the current role player of the 'who' role
# end
# end
# greeting do
-# p "Hello #{who.say}!"
+# p 'Hello #{who.say}!'
# end
# end
#
# class Greeter
# def initialize(player)
# #@who = player
# end
# end
#
-# Greeter.new('world').greeting #Will print "Hello world!"
+# Greeter.new('world').greeting #Will print 'Hello world!'
#maroon is base on Marvin which was the first injectionless language for DCI
#being injectionless there's no runtime extend or anything else impacting the performance. There' only regular method invocation even when using role methods
#Author:: Rune Funch Søltoft (funchsoltoft@gmail.com)
#License:: Same as for Ruby
##
-Context::generate_files_in 'generated'
-context :Context do
- role :roles do
- end
- role :interactions do
- end
- role :defining_role do
- end
- role :role_alias do
- end
- role :alias_list do
- end
- role :cached_roles_and_alias_list do
- end
+c = context :Context do
- #define is the only exposed method and can be used to define a context (class)
- #if maroon/kernel is required calling context of Context::define are equivalent
- #params
- #name:: the name of the context. Since this is used as the name of a class, class naming convetions should be used
- #block:: the body of the context. Can include definitions of roles (through the role method) or definitions of interactions
- #by simply calling a method with the name of the interaction and passing a block as the body of the interaction
- define :block => :block, :self => self do |*args|
+ def self.define(*args, &block)
@@with_contracts ||= nil
@@generate_file_path ||= nil
- alias method_missing role_or_interaction_method
+ (alias :method_missing :role_or_interaction_method)
+
base_class, ctx, default_interaction, name = self.send(:create_context_factory, args, block)
- ctx.generate_files_in(args.last()) if args.last().instance_of? FalseClass or args.last().instance_of? TrueClass
- return ctx.send(:finalize, name, base_class, default_interaction)
+ if (args.last.instance_of?(FalseClass) or args.last.instance_of?(TrueClass)) then
+ ctx.generate_files_in(args.last)
+ end
+ return ctx.send(:finalize, name, base_class, default_interaction, @@generate_file_path, @@with_contracts)
+
end
- generate_files_in :block => :b,:self => self do |*args|
- return role_or_interaction_method(:generate_files_in, *args, &b) if block_given?
-
+ def self.generate_files_in(*args, &b)
+ if block_given? then
+ return role_or_interaction_method(:generate_files_in, *args, &b)
+ end
@@generate_file_path = args[0]
+
end
private
- with_contracts self do |*args|
- return @@with_contracts if args.length == 0
+
+ def get_definitions(b)
+ sexp = b.to_sexp
+ unless is_definition? sexp[3]
+ sexp = sexp[3]
+ if sexp
+ sexp = sexp.select do |exp|
+ is_definition? exp
+ end
+ end
+ sexp ||= []
+ end
+
+ sexp.select do |exp|
+ is_definition? exp
+ end
+ end
+
+ def self.create_context_factory(args, block)
+ name, base_class, default_interaction = *args
+ if default_interaction and (not base_class.instance_of?(Class)) then
+ base_class = eval(base_class.to_s)
+ end
+ if base_class and ((not default_interaction) and (not base_class.instance_of?(Class))) then
+ base_class, default_interaction = default_interaction, base_class
+ end
+ ctx = Context.new
+ ctx.instance_eval {
+ sexp = block.to_sexp
+ temp_block = sexp[3]
+ i = 0
+
+ while i < temp_block.length
+ exp = temp_block[i]
+ unless temp_block[i-2] && temp_block[i-2][0] == :call && temp_block[i-1] && temp_block[i-1][0] == :args
+ if exp[0] == :defn || exp[0] == :defs
+ add_method(exp)
+ temp_block.delete_at i
+ i -= 1
+ elsif exp[0] == :call && exp[1] == nil && exp[2] == :private
+ @private = true
+ end
+ end
+ i += 1
+ end
+ ctx.instance_eval &block
+ }
+
+ return [base_class, ctx, default_interaction, name]
+
+ end
+
+ def self.with_contracts(*args)
+ return @@with_contracts if (args.length == 0)
value = args[0]
- raise 'make up your mind! disabling contracts during execution will result in undefined behavior' if @@with_contracts && !value
+ if @@with_contracts and (not value) then
+ raise('make up your mind! disabling contracts during execution will result in undefined behavior')
+ end
@@with_contracts = value
+
end
- ##
- #Defines a role with the given name
- #role methods can be defined inside a block passed to this method
- # = Example
- # role :who do
- # say do
- # p @who
- # end
- # end
- #The above code defines a role called 'who' with a role method called say
- ##
- role :block => :b do |*args|
- role_name = args[0]
- return role_or_interaction_method(:role, *args, &b) if args.length != 1 or not (role_name.instance_of? Symbol)
+ def createInfo(definition)
+ MethodInfo.new(definition, @defining_role, @private)
+ end
+ def is_definition?(exp)
+ exp && (exp[0] == :defn || exp[0] == :defs)
+ end
+
+ def role(*args, &b)
+ role_name = args[0]
+ if (args.length.!=(1) or (not role_name.instance_of?(Symbol))) then
+ return role_or_interaction_method(:role, *args, &b)
+ end
@defining_role = role_name
+ @roles = {} unless @roles
@roles[role_name] = Hash.new
- yield if block_given?
- @defining_role = nil
- end
- initialize :block => :b do |*args|
- if block_given?
- role_or_interaction_method(:initialize, *args, &b)
- else
- @roles = Hash.new
- @interactions = Hash.new
- @role_alias = Hash.new
- @contracts = Hash.new
+ definitions = get_definitions(b)
+
+ definitions.each do |exp|
+ add_method(exp)
end
- end
- role_or_interaction_method(:private) do
- @private = true
end
- current_interpretation_context :block => :b do |*args|
- return role_or_interaction_method(:current_interpretation_context, *args, &b) if block_given?
- InterpretationContext.new(roles, contracts, role_alias, nil)
+ def current_interpretation_context(*args, &b)
+ if block_given? then
+ return role_or_interaction_method(:current_interpretation_context, *args, &b)
+ end
+ InterpretationContext.new(@roles, @contracts, @role_alias, nil)
+
end
- get_methods :block => :b do |*args|
+ def get_methods(*args, &b)
return role_or_interaction_method(:get_methods, *args, &b) if block_given?
name = args[0]
sources = (@defining_role ? (@roles[@defining_role]) : (@interactions))[name]
- if @defining_role && !sources
+ if @defining_role and (not sources) then
@roles[@defining_role][name] = []
else
- (@interactions)[name] = []
+ @interactions[name] = []
end
- end
- role :contracts do
end
- add_method :block => :b do |*args|
+ def add_method(*args, &b)
return role_or_interaction_method(:add_method, *args, &b) if block_given?
- name, method = *args
- sources = get_methods(name)
- sources << method
+ exp = args[0]
+ info = createInfo exp
+ sources = get_methods(info.name)
+ (sources << info)
end
- finalize :block => :b do |*args|
+ def finalize(*args, &b)
return role_or_interaction_method(:finalize, *args, &b) if block_given?
- name, base_class, default = *args
-
+ name, base_class, default, file_path, with_contracts = *args
code = generate_context_code(default, name)
-
- if @@generate_file_path
+ if file_path then
name = name.to_s
- complete = 'class ' + name + (base_class ? '<< ' + base_class.name : '') + '
- ' + code.to_s + '
- end'
- File.open('./' + @@generate_file_path.to_s + '/' + name + '.rb', 'w') { |f| f.write(complete) }
+ complete = ((((('class ' + name) + (base_class ? (('<< ' + base_class.name)) : (''))) + '
+ ') + code.to_s) + '
+ end')
+ File.open((((('./' + file_path.to_s) + '/') + name) + '.rb'), 'w') do |f|
+ f.write(complete)
+ end
complete
else
-
- c = base_class ? (Class.new base_class) : Class.new
- if @@with_contracts
- c.class_eval('def self.assert_that(obj)
- ContextAsserter.new(self.contracts,obj)
- end
- def self.refute_that(obj)
- ContextAsserter.new(self.contracts,obj,false)
- end
- def self.contracts
- @@contracts
- end
- def self.contracts=(value)
- raise \'Contracts must be supplied\' unless value
- @@contracts = value
- end')
- c.contracts=contracts
+ c = base_class ? (Class.new(base_class)) : (Class.new)
+ if with_contracts then
+ c.class_eval(
+ 'def self.assert_that(obj)
+ ContextAsserter.new(self.contracts,obj)
+end
+def self.refute_that(obj)
+ ContextAsserter.new(self.contracts,obj,false)
+end
+def self.contracts
+ @@contracts
+end
+def self.contracts=(value)
+ @@contracts = value
+end')
+ c.contracts = contracts
end
- Kernel.const_set name, c
- temp = c.class_eval(code)
- (temp || c)
- end
- end
+ Kernel.const_set(name, c)
+ begin
+ temp = c.class_eval(code)
+ rescue SyntaxError
+ p 'error: ' + code
+ end
- create_context_factory self do |args, block|
- name, base_class, default_interaction = *args
- #if there's two arguments and the second is not a class it must be an interaction
- if default_interaction && (!base_class.instance_of? Class) then
- base_class = eval(base_class.to_s)
+ (temp or c)
end
- base_class, default_interaction = default_interaction, base_class if base_class and !default_interaction and !base_class.instance_of? Class
- ctx = Context.new
- ctx.instance_eval &block
- return base_class, ctx, default_interaction, name
+
end
- generate_context_code :block => :b do |*args|
- return role_or_interaction_method(:generate_context_code, *args, &b) if block_given?
+ def generate_context_code(*args, &b)
+ if block_given? then
+ return role_or_interaction_method(:generate_context_code, *args, &b)
+ end
default, name = args
-
getters = ''
impl = ''
interactions = ''
@interactions.each do |method_name, methods|
methods.each do |method|
@defining_role = nil
- code = ' ' + (method.build_as_context_method method_name, current_interpretation_context)
- if method.is_private
- getters << code
- else
- interactions << code
- end
+ code = (' ' + method.build_as_context_method(current_interpretation_context))
+ method.is_private ? ((getters << code)) : ((interactions << code))
end
end
-
- if default
- interactions << '
- def self.call(*args)
- arity = ' + name.to_s + '.method(:new).arity
+ if default then
+ (interactions << (((((((('
+ def self.call(*args)
+ arity = ' + name.to_s) + '.method(:new).arity
newArgs = args[0..arity-1]
- obj = ' + name.to_s + '.new *newArgs
+ obj = ') + name.to_s) + '.new *newArgs
if arity < args.length
methodArgs = args[arity..-1]
- obj.' + default.to_s + ' *methodArgs
+ obj.') + default.to_s) + ' *methodArgs
else
- obj.' + default.to_s + '
- end
+ obj.') + default.to_s) + '
+ end
end
- '
- interactions << '
- def call(*args);' + default.to_s + ' *args; end
-'
+ '))
+ (interactions << (('
+ def call(*args);' + default.to_s) + ' *args; end
+'))
end
-
@roles.each do |role, methods|
- getters << 'attr_reader :' + role.to_s + '
- '
-
+ (getters << (('attr_reader :' + role.to_s) + '
+ '))
methods.each do |method_name, method_sources|
- raise 'Duplicate definition of ' + method_name.to_s unless method_sources.length < 2
- raise 'No source for ' + method_name.to_s unless method_sources.length > 0
-
+ unless (method_sources.length < 2) then
+ raise(('Duplicate definition of ' + method_name.to_s))
+ end
+ unless (method_sources.length > 0) then
+ raise(('No source for ' + method_name.to_s))
+ end
method_source = method_sources[0]
@defining_role = role
- rewritten_method_name = 'self_' + role.to_s + '_' + method_name.to_s
- definition = method_source.build_as_context_method rewritten_method_name, current_interpretation_context
- (impl << ' ' + definition.to_s) if definition
+
+ definition = method_source.build_as_context_method(current_interpretation_context)
+ (impl << (' ' + definition.to_s)) if definition
end
end
-
-
- interactions + '
- private
-' + getters + '
+ private_string = (getters + impl).strip! != '' ? '
+ private
+' : ''
+ impl = impl.strip! != '' ? '
' + impl + '
+ ' : '
'
+ interactions + private_string + getters + impl
+
end
- role_or_interaction_method({:block => :b}) do |*arguments|
+ def role_or_interaction_method(*arguments, &b)
method_name, on_self = *arguments
- unless method_name.instance_of? Symbol
+ unless method_name.instance_of?(Symbol) then
on_self = method_name
method_name = :role_or_interaction_method
end
+ raise(('Method with out block ' + method_name.to_s)) unless block_given?
- raise 'Method with out block ' + method_name.to_s unless block_given?
+ end
- add_method(method_name, MethodInfo.new(on_self, b.to_sexp, @private))
+ def private
+ @private = true
end
-end
\ No newline at end of file
+
+ def initialize
+ @roles = {}
+ @interactions = {}
+ @role_alias = {}
+ end
+
+end
+
+if c.instance_of? String
+ file_name = './generated/Context.rb'
+ p "writing to: " + file_name
+ File.open(file_name, 'w') do |f|
+ f.write(c)
+ end
+end