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