Permalink
Browse files

* Enable mixins.

* Bug fix: No constructor implementation was generated for classes that
  have no attributes.
* Do not use modifies like "virtual", "static" or "inline" in implementation
  code.
* Allow class definitions which are not wrapped (cplus2ruby :no_wrap => true).
* Implement a more advanced ordering of entities using their dependecies.
  • Loading branch information...
1 parent 4bef17c commit 9a68ef6cffd1dc5ec2db872579791cb1597edccd @mneumann committed Mar 13, 2008
View
@@ -1,3 +1,24 @@
module Cplus2Ruby; end
+
require 'cplus2ruby/model'
require 'cplus2ruby/compiler'
+
+#
+# Extend facets/annotations
+#
+class Module
+ def recursive_annotations
+ res = {}
+ ancestors.each { |ancestor|
+ ancestor.annotations.each { |ref, hash|
+ res[ref] ||= {}
+ res[ref] += hash if hash
+ }
+ }
+ res
+ end
+
+ def local_annotations
+ recursive_annotations() - self.superclass.recursive_annotations()
+ end
+end
@@ -16,15 +16,23 @@ def write_out(file, str)
File.open(file, 'w+') {|out| out.puts str}
end
+ def no_wrap?(klass)
+ (klass.local_annotations[:__options__] || {})[:no_wrap]
+ end
+
+ def wrap?(klass)
+ not no_wrap?(klass)
+ end
+
def all_properties_of(klass)
- klass.annotations.each do |name, options|
+ klass.local_annotations.each do |name, options|
next if options[:class] != Cplus2Ruby::Property
yield name, options
end
end
def all_methods_of(klass)
- klass.annotations.each do |name, options|
+ klass.local_annotations.each do |name, options|
next if options[:class] != Cplus2Ruby::Method
yield name, options
end
@@ -66,7 +66,7 @@ def gen_constructor(klass)
init = @model.typing.lookup_entry(:init, options, options[:type])
stmts << @model.typing.var_assgn("this->#{name}", init) unless init.nil?
end
- return "" if stmts.empty?
+ #return "" if stmts.empty?
%[
#{klass.name}::#{klass.name}()
{
@@ -85,16 +85,18 @@ def gen_property(name, options)
#
# Doesn't include the semicolon at the end.
#
- def gen_method_sig(klassname, name, options)
+ def gen_method_sig(klassname, name, options, is_declaration)
args = options[:arguments].dup
returns = args.delete(:returns) || "void"
out = ""
- out << "static " if options[:static]
- out << "inline " if options[:inline]
- out << "virtual " if options[:virtual]
+ if is_declaration
+ out << "static " if options[:static]
+ out << "inline " if options[:inline]
+ out << "virtual " if options[:virtual]
+ end
out << @model.typing.var_decl(returns, "")
- out << "\n"
+ out << " "
s = args.map {|aname, atype| @model.typing.var_decl(atype, aname) }.join(", ")
@@ -107,8 +109,8 @@ def gen_method_body(options)
"{\n" + (options[:body] || "") + "}\n"
end
- def gen_method(klassname, name, options, include_body)
- str = gen_method_sig(klassname, name, options)
+ def gen_method(klassname, name, options, include_body, is_declaration)
+ str = gen_method_sig(klassname, name, options, is_declaration)
str << gen_method_body(options) if include_body
str
end
@@ -140,37 +142,49 @@ def gen_class_declaration(klass)
}
all_methods_of(klass) {|name, options|
- stmts << gen_method(nil, name, options, options[:inline])
+ stmts << gen_method(nil, name, options, options[:inline], true)
}
- %[
- struct #{klass.name} : #{sc}
- {
- typedef #{sc} super;
-
- #{klass.name}();
-
- #{m[:free]}
- #{m[:mark]}
-
- #{stmts.join("; \n")};
- };
- ]
+ if no_wrap?(klass)
+ %[
+ struct #{klass.name}
+ {
+ #{stmts.join("; \n")};
+ };
+ ]
+ else
+ %[
+ struct #{klass.name} : #{sc}
+ {
+ typedef #{sc} super;
+
+ #{klass.name}();
+
+ #{m[:free]}
+ #{m[:mark]}
+
+ #{stmts.join("; \n")};
+ };
+ ]
+ end
end
def gen_class_impl(klass)
# FIXME: helper_codes
stmts = []
- stmts << gen_constructor(klass)
- [:free, :mark].each {|kind|
- stmts << gen_free_or_mark_method(klass, kind)
- }
+ if wrap?(klass)
+ stmts << gen_constructor(klass)
+
+ [:free, :mark].each {|kind|
+ stmts << gen_free_or_mark_method(klass, kind)
+ }
+ end
all_methods_of(klass) do |name, options|
next if options[:inline]
- stmts << gen_method(klass.name, name, options, true)
+ stmts << gen_method(klass.name, name, options, true, false)
end
stmts.join("\n")
View
@@ -10,11 +10,16 @@ class Cplus2Ruby::Model
attr_reader :code
attr_reader :includes
+ def next_order_cnt
+ @order_cnt += 1
+ end
+
def initialize
@typing = Cplus2Ruby::Typing.new
@code = ""
@includes = []
@settings = default_settings()
+ @order_cnt = 0
end
def finish!
@@ -31,14 +36,35 @@ def entities
entities
end
+ def entity_usage(klass, other)
+ usage_cnt = 0
+ klass.local_annotations.each do |name, opts|
+ usage_cnt += 1 if opts[:arguments] and opts[:arguments].values.include?(other)
+ usage_cnt += 1 if opts[:type] and opts[:type] == other
+ end
+ usage_cnt
+ end
+
def entities_ordered
entities().sort {|a, b|
if a.ancestors.include?(b)
+ # a 'after' b (a > b)
1
elsif b.ancestors.include?(a)
-1
else
- 0
+ ea = entity_usage(a, b)
+ eb = entity_usage(b, a)
+
+ if ea > 0 and eb == 0
+ -1
+ elsif eb > 0 and ea == 0
+ 1
+ else
+ ao = (a.heritage(:__options__) || {})[:order] || 0
+ bo = (b.heritage(:__options__) || {})[:order] || 0
+ ao <=> bo
+ end
end
}
end
@@ -100,21 +126,6 @@ def self.compile(*args)
end
module Cplus2Ruby::Entity
- def public(*args)
- # FIXME
- super
- end
-
- def protected(*args)
- # FIXME
- super
- end
-
- def private(*args)
- # FIXME
- super
- end
-
def property(name, type=Object, options={})
raise ArgumentError if options[:type]
options[:type] = type
@@ -167,23 +178,13 @@ def virtual(*virtuals)
ann! name, :virtual => true
end
end
-
-=begin
- def helper_header(body)
- for which class.
- ann!
- Cplus2Ruby.model[self].add_helper_header(body)
- end
-
- def helper_code(body)
- Cplus2Ruby.model[self].add_helper_code(body)
- end
-=end
end
class Module
- def cplus2ruby
+ def cplus2ruby(hash={})
include Cplus2Ruby::Entity
extend Cplus2Ruby::Entity
+ ann! :__options__, hash
+ ann! :__options__, :order => Cplus2Ruby.model.next_order_cnt if hash[:order].nil?
end
end
@@ -102,6 +102,7 @@ def gen_init(mod_name)
out << " VALUE klass;\n"
@model.entities_ordered.each do |klass|
+ next if no_wrap?(klass)
n = klass.name
out << %{ klass = rb_eval_string("#{n}");\n}
out << %{ rb_define_alloc_func(klass, #{n}_alloc__);\n}
@@ -136,10 +137,12 @@ def gen_wrapper_file(mod_name)
out << %{#include "#{mod_name}.h"\n\n}
@model.entities_ordered.each do |klass|
+ next if no_wrap?(klass)
+
out << gen_allocator(klass)
all_methods_of(klass) do |name, options|
- out << gen_method_wrapper(klass, name, options)
+ out << (gen_method_wrapper(klass, name, options) || "")
end
all_properties_of(klass) do |name, options|

0 comments on commit 9a68ef6

Please sign in to comment.