Brian Silverman | 8efe23e | 2013-07-07 23:31:37 -0700 | [diff] [blame] | 1 | begin |
| 2 | require "sha1" |
| 3 | rescue LoadError |
| 4 | require "digest/sha1" |
| 5 | end |
| 6 | |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 7 | module Target |
| 8 | end |
| 9 | class Target::Node |
| 10 | attr_accessor :created_by |
| 11 | end |
| 12 | class Target::QFile < Target::Node |
| 13 | def initialize() #needs to know repo_path, |
| 14 | @class_types = [] |
| 15 | end |
| 16 | def add_type(type) |
| 17 | @class_types << type |
| 18 | end |
| 19 | def extern=(value) |
| 20 | @class_types.each do |type| |
| 21 | type.extern=value |
| 22 | end |
| 23 | end |
| 24 | def make_cpp_tree(rel_path) |
| 25 | cpp_tree = DepFilePair.new(rel_path) |
| 26 | cpp_tree.add_header_include("\"aos/common/macros.h\"") |
| 27 | cpp_tree.add_header_include("\"aos/common/queue.h\"") |
| 28 | @class_types.each do |type| |
| 29 | cpp_tree.get(type) |
| 30 | end |
| 31 | return cpp_tree |
| 32 | end |
| 33 | end |
| 34 | class Target::QInclude < Target::Node |
| 35 | def initialize(path) |
| 36 | @path = path |
| 37 | end |
| 38 | def create(cpp_tree) |
| 39 | # inc = cpp_tree.header.add_include("\"#{@path}\"") |
| 40 | inc = cpp_tree.add_header_include("\"#{@path}\"") |
| 41 | cpp_tree.set(self,inc) |
| 42 | end |
| 43 | end |
| 44 | class Target::QueueGroupDec < Target::Node |
| 45 | attr_accessor :name,:loc,:parent,:queues |
| 46 | def initialize(name) |
| 47 | @name = name |
| 48 | @queues = [] |
| 49 | @subs = {} |
| 50 | end |
| 51 | def root() |
| 52 | @parent.root() |
| 53 | end |
| 54 | def []=(key,val) |
| 55 | #puts "#{key}= #{val}" |
| 56 | @subs[key] = val |
| 57 | end |
| 58 | def extern=(value) |
| 59 | @extern=value |
| 60 | end |
| 61 | def get_name() |
| 62 | if(@parent) |
| 63 | return "#{@parent.get_name}.#{@name}" |
| 64 | else |
| 65 | return "#{@name}" |
| 66 | end |
| 67 | end |
| 68 | def to_cpp_id(id) |
| 69 | name = "#{@name}::#{id}" |
| 70 | return @parent.to_cpp_id(name) if(@parent) |
| 71 | return name |
| 72 | end |
| 73 | def [](key) |
| 74 | #puts "#{key}" |
| 75 | @subs[key] |
| 76 | end |
| 77 | def add_queue(queue) |
| 78 | @queues.push(queue) |
| 79 | end |
| 80 | def hash_with_name(name) |
| 81 | ts = (@queues.collect { |queue| |
| 82 | queue.msg_hash() |
| 83 | }).join("") + name |
Brian Silverman | 8efe23e | 2013-07-07 23:31:37 -0700 | [diff] [blame] | 84 | return "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}" |
brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame] | 85 | end |
| 86 | def create(cpp_tree) |
| 87 | return if(@extern) |
| 88 | namespace = cpp_tree.get(@loc) |
| 89 | type_class = Types::Class.new(namespace,@name) |
| 90 | cpp_tree.set(self,type_class) #breaks infinite recursion |
| 91 | type_class.set_parent("public ::aos::QueueGroup") |
| 92 | @queues.each do |queue| |
| 93 | type_class.add_member(:public,queue.create_usage(cpp_tree)) |
| 94 | namespace.add_pre_swig("%immutable #{@name}::#{queue.name}") |
| 95 | end |
| 96 | create_Constructor(type_class,cpp_tree) |
| 97 | namespace.add(type_class) |
| 98 | end |
| 99 | def create_Constructor(type_class,cpp_tree) |
| 100 | member_func = CPP::Constructor.new(type_class) |
| 101 | type_class.add_member(:public,member_func) |
| 102 | #cpp_tree.cc_file.add_funct(member_func) |
| 103 | member_func.args << "const char *name"; |
| 104 | member_func.args << "uint32_t hash"; |
| 105 | member_func.add_cons("::aos::QueueGroup","name", "hash") |
| 106 | @queues.each do |queue| |
| 107 | member_func.args << "const char *#{queue.name}_name"; |
| 108 | member_func.add_cons(queue.name,"#{queue.name}_name") |
| 109 | end |
| 110 | end |
| 111 | end |
| 112 | class Target::QueueGroup < Target::Node |
| 113 | attr_accessor :name,:loc |
| 114 | def initialize(type,name) |
| 115 | @type,@name = type,name |
| 116 | end |
| 117 | def type_name() |
| 118 | if(@type.loc == @loc) #use relative name |
| 119 | return @type.name |
| 120 | else #use full name |
| 121 | return @type.loc.to_cpp_id(@type.name) |
| 122 | end |
| 123 | end |
| 124 | def create(cpp_tree) |
| 125 | namespace = cpp_tree.get(@loc) |
| 126 | type = cpp_tree.get(@type) |
| 127 | cpp_tree.set(self,self) |
| 128 | namespace.add_cc("static #{type_name} *#{@name}_ptr") |
| 129 | counter = "#{@name}_counter" |
| 130 | namespace.add_cc("static int #{counter}") |
| 131 | |
| 132 | str = <<COMMENT_END |
| 133 | Schwarz counter to construct and destruct the #{@name} object. |
| 134 | Must be constructed before &#{@name} is constructed so that #{@name}_ptr |
| 135 | is valid so we can store a reference to the object. |
| 136 | COMMENT_END |
| 137 | str.split(/\n/).each do |str_sec| |
| 138 | namespace.class_comment(str_sec) |
| 139 | end |
| 140 | init_class = namespace.add_class("InitializerFor_" + @name).add_dep(type) |
| 141 | |
| 142 | |
| 143 | init_class.add_cc_comment( |
| 144 | "The counter is initialized at load-time, i.e., before any of the static", |
| 145 | "objects are initialized.") |
| 146 | |
| 147 | |
| 148 | cons = CPP::Constructor.new(init_class) |
| 149 | init_class.add_member(:public,cons) |
| 150 | cons.suite << if_stmt = CPP::If.new("0 == #{counter}++") |
| 151 | if_stmt.suite << "printf(#{"making a #{@name}!\n".inspect})" |
| 152 | |
| 153 | cons_call = CPP::FuncCall.new("new #{type_name}") |
| 154 | cons_call.args.push(@loc.queue_name(@name).inspect) |
| 155 | |
| 156 | cons_call.args.push(@type.hash_with_name(@loc.queue_name(@name).inspect)) |
| 157 | @type.queues.collect do |queue| |
| 158 | cons_call.args.push(@loc.queue_name(@name + "." + queue.name).inspect) |
| 159 | end |
| 160 | if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call) |
| 161 | if_stmt.else_suite << CPP::FuncCall.build("printf","already made a #{@name}\n".inspect) |
| 162 | |
| 163 | |
| 164 | destruct = CPP::Destructor.new(init_class) |
| 165 | destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}") |
| 166 | if_stmt.suite << "printf(#{"deleting a #{@name}!! :) !!\n".inspect})" |
| 167 | if_stmt.suite << "delete #{@name}_ptr" |
| 168 | if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL") |
| 169 | |
| 170 | init_class.add_member(:public,destruct) |
| 171 | init_class.static = true |
| 172 | init_class.dec = @name + "_initializer"; |
| 173 | |
| 174 | str = <<COMMENT_END |
| 175 | Create a reference to the new object in the pointer. Since we have already |
| 176 | created the initializer |
| 177 | COMMENT_END |
| 178 | comments = str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)} |
| 179 | comments << "static UNUSED_VARIABLE #{type_name} &#{@name} = " + |
| 180 | "#{@name}_initializer.get()" |
| 181 | namespace.add_post_swig("%immutable #{@name}_initializer") |
| 182 | namespace.add_post_swig(CPP::SwigPragma.new("java", "modulecode", CPP::Suite.new(["public static final #{@name} = get#{@name.capitalize}_initializer().get()"]))) |
| 183 | ifdef_statement = CPP::IfnDef.new(CPP::Suite.new(comments)) |
| 184 | ifdef_statement.name = "SWIG" |
| 185 | namespace.add(ifdef_statement) |
| 186 | |
| 187 | |
| 188 | get = init_class.def_func(type_name,"get") #.add_dep(type) |
| 189 | get.pre_func_types = "&" |
| 190 | get.suite << CPP::Return.new("*#{@name}_ptr") |
| 191 | end |
| 192 | end |