Skip to content

Instantly share code, notes, and snippets.

@kenpusney
Created August 14, 2013 13:02
Show Gist options
  • Save kenpusney/6230837 to your computer and use it in GitHub Desktop.
Save kenpusney/6230837 to your computer and use it in GitHub Desktop.
use FM.rb for fast OO Modeling see https://github.com/kenpusney/fm.rb
class FMClass
def initialize
@deps = []
@childs = []
@comps = []
@parent = nil
@methods = {
:public => [],
:private => []
}
end
def dump(driver = nil)
info = {
:deps => @deps,
:childs => @childs,
:parent => @parent,
:methods => @methods,
:comps => @comps,
:self => self.to_s
}
if driver
driver.dump(info)
else
info
end
end
## Class Relations
def compose(cls)
cls.composed_by(self)
end
def composed_by(cls)
@deps << cls
@comps << cls
@deps.uniq!
end
def depend(cls)
@deps << cls
@deps.uniq!
end
def depended_by(other)
other.depend(self)
end
def inherit( parent )
parent.derive(self)
@parent = parent
end
def derive(cls)
@childs << cls
@childs.uniq!
end
def to_s
self.class.name
end
def to_sym
self.to_s.to_sym
end
def add_method(mtd)
acl = (mtd =~ /^\b*-/)
resolve_signature(acl,mtd)
end
alias_method :is_a, :inherit
alias_method :has_a, :composed_by
alias_method :<<, :add_method
private
def resolve_signature(acl = true,mtd = "")
if mtd.empty?
return
else
mtd =~ /^ \s* [+\-]? # acl
\s* (\w+)\s* # method name
\( (.*) \) # method argument list
:?\s*(\w+)? # method return type
/x
mtd_name = $1
mtd_args = $2.empty? ? nil : $2
mtd_ret = $3
if mtd_args
mtd_args = mtd_args.split(',').map do | elem |
pair = elem.split ':'
{ :type => pair[1].strip, :name => pair[0].strip }
end
end
@methods[ acl ? :private : :public] << {
:name => mtd_name,
:return => mtd_ret,
:args => mtd_args
}
end
end
end
class FMDriver
def initialize
@info = nil
@body = ""
end
[:deps,:parent,:comps,:methods].each do |iattr|
define_method("dump_#{iattr}".to_sym) { @info[iattr] }
end
def dump(info)
@info = info
dump_all
end
def dump_all
"deps: " + dump_deps.to_s +
"\nparent: " + dump_parent.to_s +
"\ncomps: " + dump_comps.to_s +
"\nmethods: " + dump_methods.to_s
end
end
class CPPDriver < FMDriver
def dump_all
dump_deps
dump_parent
dump_comps
dump_methods
dump_end
end
def dump_deps
@body += @info[:deps].map { |elem|
if [:int,:float,:short,:long,:double,:char,:bool].include? elem.to_sym
""
else
"#include <#{elem}.h>\n"
end
}.join("")
@body
end
def dump_parent
@body += "class #{@info[:self]}#{@info[:parent]? ':public': ''} #{@info[:parent]}{\n"
@body
end
def dump_comps
cnt = 0
@body += @info[:comps].map do |elem|
"\t#{elem} __#{elem}_#{cnt};\n"
end .join("")
@body
end
def dump_methods
for k,v in @info[:methods]
@body += "#{k}:\n"
@body += v.reduce("") do |total,mem|
total + dump_sign(mem)
end
end
@body
end
def dump_sign(elem)
"\t#{elem[:return]} #{elem[:name]}(#{dump_args(elem[:args])});\n"
end
def dump_args(args)
if args
args.map {|elem|
"#{elem[:type]} #{elem[:name]}"
}.join(", ")
else
""
end
end
def dump_end
@body +="};\n"
@body
end
end
class A < FMClass
end
class B < FMClass
end
class C < FMClass
end
a = A.new
b = B.new
c = C.new
a.is_a b
b.is_a c
a.has_a c
a.has_a :int
a << "+hula(pululu:int, kim:string):int"
a << "-blublu():void"
c.derive b
puts a.dump(CPPDriver.new)
puts b.dump(CPPDriver.new)
puts c.dump(CPPDriver.new)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment