|
class Symbol |
|
def [](*args) |
|
a = [self, args, '[]'] |
|
a.instance_eval('@_type_flag = \'[]\'') |
|
a |
|
end |
|
def <<(*ary) |
|
a = [self, ary.flatten, '<'] |
|
a.instance_eval('@_type_flag = \'<\'') |
|
a |
|
end |
|
end |
|
class Array |
|
def < (*ary) |
|
raise NoMethodError, "undefined method `<' for Array:Class", caller(1) if @_type_flag.nil? |
|
a = [self, ary.flatten, '<'] |
|
a.instance_eval('@_type_flag = \'<\'') |
|
a |
|
end |
|
alias old_ll << |
|
def << (*args) |
|
return old_ll *args if @_type_flag.nil? |
|
return self < args |
|
end |
|
end |
|
|
|
def Def(name, &proc) |
|
name = name[] if (!name.is_a?(Array)) |
|
raise TypeError, "wrong type of argument." if name[2] != '[]' |
|
name[0] = name[0].to_sym |
|
params = proc.parameters |
|
needArgs = (params.index {|x| x[0] == :opt || x[0] == :rest } || params.size - 1) + 1 |
|
hasRest = !(params.index {|x| x[0] == :rest}).nil? |
|
hasBlock = !(params.index {|x| x[0] == :block}).nil? |
|
|
|
if (name.is_a?(Array) and name.size == 3) |
|
|
|
time = Time.now |
|
method_name = "_#{name[0]}__bind_#{time.to_i}_#{time.usec}" |
|
define_method(method_name, &proc) |
|
define_method(name[0]) do |*args, &newproc| |
|
raise ArgumentError, "wrong number of arguments (#{args.size} for #{needArgs})", caller(1) if (args.size < needArgs || (!hasRest and args.size > needArgs.size)) |
|
for n in 0...[name[1].size,args.size].min |
|
needType = name[1][n].is_a?(Array) ? name[1][n] : [name[1][n]] |
|
|
|
needType = needType.map {|x| |
|
if x.is_a?(Class) |
|
x |
|
else |
|
if (self.class.respond_to?(:_template_list)) |
|
raise TypeError, "", caller(0) if (self.class._template_list[x].nil?) |
|
self.class._template_list[x] |
|
else |
|
raise TypeError, "", caller(0) |
|
end |
|
end |
|
}.flatten |
|
raise TypeError, "wrong type of argument #{params[n][1]} (#{args[n].class.name} for #{needType})", caller(3) unless (needType.any? {|x| args[n].kind_of?(x)}) |
|
end |
|
if (hasBlock) then method(method_name).call(*args, &newproc) else method(method_name).call(*args) end |
|
end |
|
end |
|
end |
|
class Object |
|
def is_klass? |
|
return false |
|
end |
|
end |
|
|
|
Def :Class[[Symbol, String, Array]] do |name = {}, &_proc| |
|
|
|
parents = [] |
|
_template = [] |
|
if (name.is_a?(Array)) |
|
raise TypeError, 'wrong type of argument' if name.size != 3 |
|
if (name[2] == '<') |
|
parents = name[1] |
|
name = name[0] |
|
end |
|
if (name[2] == '[]') |
|
_template = name[1] |
|
name = name[0] |
|
end |
|
end |
|
|
|
name = name.to_sym |
|
parents.uniq! |
|
o = if self.respond_to?(:const_set) then self else Object end |
|
parents.map! {|x| if x.is_a?(Symbol) then o.const_get(x) else x end } |
|
|
|
mkClass = proc do |template_matchs = []| |
|
_template_list = {} |
|
_template.each_index{|x| _template_list[_template[x]] = template_matchs[x]} |
|
myklass = Class.new do |
|
@_parents_flat = [] |
|
@_template_list = _template_list |
|
|
|
def self._parents_flat |
|
return @_parents_flat |
|
end |
|
def self._template_list |
|
return @_template_list |
|
end |
|
|
|
parents = parents.map { |p| |
|
[p, p.klass_parents_flat] if (p.is_klass?) |
|
}.flatten.uniq |
|
|
|
parents.each { |p| |
|
unless (@_parents_flat.include? p) |
|
@_parents_flat << p |
|
raise TypeError, "Class is required", caller(3) if (!p.is_klass?) |
|
@_template_list.merge! p.klass_templte_list |
|
instance_eval &p.klass_init_proc |
|
end |
|
} |
|
|
|
instance_eval &_proc |
|
|
|
def is_a?(type) |
|
org = super(type) |
|
return true if org |
|
self.class._parents_flat.any? {|x| x == type} |
|
end |
|
|
|
end |
|
myklass.define_singleton_method(:is_klass?) {true} |
|
myklass.define_singleton_method(:klass_init_proc) { _proc } |
|
myklass.define_singleton_method(:klass_templte_list) { @_template_list } |
|
myklass.define_singleton_method(:klass_parents_flat) { @_parents_flat } |
|
|
|
myklass |
|
end |
|
if (_template.size == 0) |
|
klass = mkClass.call() |
|
o.const_set(name, klass) |
|
else |
|
o.const_set(name, Class.new do |
|
def initialize(mkClass, needTemplate = 0) |
|
@needTemplate = needTemplate |
|
@mkClass = mkClass |
|
@doneClass = {} |
|
end |
|
def [](*args) |
|
_template = args |
|
raise ArgumentError if (_template.size != @needTemplate) |
|
@doneClass[_template] = @mkClass.call(_template) if @doneClass[_template].nil? |
|
@doneClass[_template] |
|
end |
|
end.new(mkClass, _template.size)) |
|
end |
|
end |
|
|
|
module WoW |
|
Class :Aaa do |
|
Def :hello do |
|
puts 'xy' |
|
end |
|
end |
|
Class :BBB << :Aaa do |
|
Def :fuck do |
|
puts 'xy' |
|
end |
|
end |
|
|
|
Class :MyClass[:T] < [:Aaa, :BBB] do |
|
alias_method :aloha, :hello |
|
Def :hello[[String,Integer], :T] {|a,b, *z,&c| |
|
print a,b,*z |
|
aloha() |
|
c.call() |
|
} |
|
end |
|
end |
|
|
|
|
|
klass = WoW::MyClass[[String,Integer]].new |
|
klass.hello(1,"a","3","4","5") {puts 'x'} |
|
klass.fuck() |
|
print klass.is_a?(Float).to_s + "\n" |
|
print klass.is_a?(WoW::MyClass[String]).to_s + "\n" |
|
print klass.is_a?(WoW::MyClass[Integer]).to_s + "\n" |
|
print klass.is_a?(WoW::BBB).to_s + "\n" |
|
print klass.is_a?(Object).to_s + "\n" |