blob: a65aca3b853eb3d689713ee125a4a59531bddc26 [file] [log] [blame]
Brian Silverman8efe23e2013-07-07 23:31:37 -07001begin
2 require "sha1"
3rescue LoadError
4 require "digest/sha1"
5end
6
Parker Schuh711db3e2014-02-12 09:47:34 -08007class Target::StructBase < Target::Node
8 def create_DoGetType(type_class, cpp_tree)
Brian Silverman665e60c2014-02-12 13:57:10 -08009 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","DoGetType")
Parker Schuh711db3e2014-02-12 09:47:34 -080010 member_func.static = true
Parker Schuh711db3e2014-02-12 09:47:34 -080011 fields = []
Brian Silverman665e60c2014-02-12 13:57:10 -080012 register_members = []
Parker Schuh711db3e2014-02-12 09:47:34 -080013 @members.each do |member|
14 tId = member.getTypeID()
15 fieldName = member.name.inspect
16 if(member.respond_to?(:add_TypeRegister))
Brian Silverman665e60c2014-02-12 13:57:10 -080017 register_members.push(member)
Parker Schuh711db3e2014-02-12 09:47:34 -080018 end
Austin Schuh7e958392014-10-21 22:16:23 -070019 fields << "new ::aos::MessageType::Field{#{tId}, #{member.respond_to?(:length) ? member.length : 0}, #{fieldName}}"
Parker Schuh711db3e2014-02-12 09:47:34 -080020 end
Brian Silverman665e60c2014-02-12 13:57:10 -080021 register_members.uniq do |member|
22 member.type
23 end.each do |member|
24 member.add_TypeRegister(cpp_tree, type_class, member_func)
25 end
Parker Schuh711db3e2014-02-12 09:47:34 -080026 id = getTypeID()
Brian Silverman3451d0e2014-02-14 13:23:51 -080027 member_func.suite << ("static const ::aos::MessageType kMsgMessageType(#{type_class.parent_class ? type_class.parent_class + '::Size()' : 0}, #{id}, #{(@loc.respond_to?(:queue_name) ? @loc.queue_name(@name) : "#{@loc.get_name()}.#{@name}").inspect}, {" +
Parker Schuh711db3e2014-02-12 09:47:34 -080028 "#{fields.join(", ")}})");
29 type_class.add_member(member_func)
Brian Silverman665e60c2014-02-12 13:57:10 -080030 member_func.suite << "::aos::type_cache::Add(kMsgMessageType)"
Parker Schuh711db3e2014-02-12 09:47:34 -080031 member_func.suite << CPP::Return.new("&kMsgMessageType")
32 end
Brian Silverman16c82972014-02-13 15:36:40 -080033 def create_InOrderConstructor(type_class, cpp_tree)
Daniel Pettid5760ba2014-11-14 12:38:00 -080034 if @members.empty?
35 return
36 end
Brian Silverman16c82972014-02-13 15:36:40 -080037 cons = CPP::Constructor.new(type_class)
38 type_class.add_member(cons)
39 @members.each do |member|
40 if member.respond_to?(:type_name)
Austin Schuh7e958392014-10-21 22:16:23 -070041 type_name = "#{member.type_name(cpp_tree)} #{member.name}_in"
Brian Silverman16c82972014-02-13 15:36:40 -080042 else
Austin Schuh7e958392014-10-21 22:16:23 -070043 type_name = member.create_usage(cpp_tree, "#{member.name}_in")
Brian Silverman16c82972014-02-13 15:36:40 -080044 end
45
Austin Schuh7e958392014-10-21 22:16:23 -070046 cons.args << type_name
Brian Silverman16c82972014-02-13 15:36:40 -080047 cons.add_cons(member.name, member.name + '_in')
48 end
49 end
50 def create_DefaultConstructor(type_class, cpp_tree)
51 cons = CPP::Constructor.new(type_class)
52 type_class.add_member(cons)
53 cons.add_cons(type_class.parent_class) if type_class.parent_class
54 cons.suite << CPP::FuncCall.build('Zero')
55 end
56 def create_Zero(type_class,cpp_tree)
57 member_func = CPP::MemberFunc.new(type_class,"void","Zero")
58 type_class.add_member(member_func)
59 @members.each do |elem|
60 elem.zeroCall(member_func.suite)
61 end
62 member_func.suite << CPP::FuncCall.new(type_class.parent_class + '::Zero') if type_class.parent_class
63 end
64 def create_Size(type_class,cpp_tree)
65 member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
66 member_func.inline = true
67 member_func.static = true
68 type_class.add_member(member_func.forward_dec)
69 size = 0
70 @members.each do |elem|
71 size += elem.size
72 end
73 if type_class.parent_class
74 member_func.suite << CPP::Return.new(CPP::Add.new(size,
75 "#{type_class.parent_class}::Size()"))
76 else
77 member_func.suite << CPP::Return.new(size)
78 end
79 end
80 def create_Serialize(type_class,cpp_tree)
81 member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
82 type_class.add_member(member_func)
83 member_func.args << "char *buffer"
84 member_func.suite << "#{type_class.parent_class}::Serialize(buffer)" if type_class.parent_class
85 member_func.const = true
86 offset = type_class.parent_class ? type_class.parent_class + '::Size()' : '0'
87 @members.each do |elem|
88 elem.toNetwork(offset,member_func.suite)
89 offset += " + #{elem.size}";
90 end
91 member_func.suite << CPP::Return.new(CPP::FuncCall.new('Size'))
92 end
93 def create_Deserialize(type_class,cpp_tree)
94 member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
95 type_class.add_member(member_func)
96 member_func.args << "const char *buffer"
97 member_func.suite << "#{type_class.parent_class}::Deserialize(buffer)" if type_class.parent_class
98 offset = type_class.parent_class ? type_class.parent_class + '::Size()' : '0'
99 @members.each do |elem|
100 elem.toHost(offset,member_func.suite)
101 offset += " + #{elem.size}";
102 end
103 member_func.suite << CPP::Return.new(CPP::FuncCall.new('Size'))
104 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800105 def simpleStr()
106 return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
107 end
108 def getTypeID()
Brian Silverman1885bd02014-02-13 12:28:12 -0800109 return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) | size).to_s(16)
Parker Schuh711db3e2014-02-12 09:47:34 -0800110 end
111 def add_member(member)
112 @members << member
113 end
114 def size()
115 return @size if(@size)
116 @size = 0
117 @members.each do |elem|
118 @size += elem.size
119 end
120 return @size
121 end
122end
123
124class Target::MessageDec < Target::StructBase
brians343bc112013-02-10 01:53:46 +0000125 attr_accessor :name,:loc,:parent,:msg_hash
126 def initialize(name)
127 @name = name
128 @members = []
129 end
130 def extern=(value)
131 @extern=value
132 end
133 def get_name()
134 if(@parent)
135 return "#{@parent.get_name}.#{@name}"
136 else
137 return "#{@name}"
138 end
139 end
brians343bc112013-02-10 01:53:46 +0000140 def create_Print(type_class,cpp_tree)
141 member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
142 type_class.add_member(member_func)
143 member_func.args << "char *buffer"
144 member_func.args << "size_t length"
145 member_func.const = true
146 format = "\""
147 args = []
148 @members.each do |elem|
149 format += ", "
150 format += elem.toPrintFormat()
Parker Schuh343481e2014-02-09 18:28:43 -0800151 elem.fetchPrintArgs(args)
brians343bc112013-02-10 01:53:46 +0000152 end
Parker Schuh343481e2014-02-09 18:28:43 -0800153 format += "\""
154 member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
155 member_func.suite << "buffer += super_size"
156 member_func.suite << "length -= super_size"
Daniel Pettid5760ba2014-11-14 12:38:00 -0800157 if !args.empty?
158 member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
159 else
160 # snprintf will return zero.
161 member_func.suite << "return super_size"
162 end
brians343bc112013-02-10 01:53:46 +0000163 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800164 def create_GetType(type_class, cpp_tree)
Brian Silverman665e60c2014-02-12 13:57:10 -0800165 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","GetType")
166 type_class.add_member(member_func)
167 member_func.static = true
Parker Schuh711db3e2014-02-12 09:47:34 -0800168 member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
Brian Silverman665e60c2014-02-12 13:57:10 -0800169 member_func.suite << CPP::Return.new("getter.Get()")
Parker Schuh711db3e2014-02-12 09:47:34 -0800170 end
brians343bc112013-02-10 01:53:46 +0000171 def self.builder_loc(loc)
172 return @builder_loc if(@builder_loc)
173 return @builder_loc = loc.root.get_make("aos")
174 end
175 def type_name(builder_loc,name)
176 if(builder_loc == @loc) #use relative name
177 return name
178 else #use full name
179 return @loc.to_cpp_id(name)
180 end
181 end
182 def create(cpp_tree)
183 return self if(@extern)
184 orig_namespace = namespace = cpp_tree.get(@loc)
185 name = ""
186 if(namespace.class < Types::Type) #is nested
187 name = namespace.name + "_" + name
188 namespace = namespace.space
189 end
190 type_class = namespace.add_struct(name + @name)
191 if(name.length > 0)
192 orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
193 end
194 cpp_tree.set(self,type_class)
195 type_class.set_parent("public ::aos::Message")
Parker Schuh711db3e2014-02-12 09:47:34 -0800196 ts = self.simpleStr()
Brian Silverman8efe23e2013-07-07 23:31:37 -0700197 self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
Austin Schuh7e958392014-10-21 22:16:23 -0700198 type_class.add_member("enum {kQueueLength = 100, kHash = #{self.msg_hash}}")
brians343bc112013-02-10 01:53:46 +0000199 @members.each do |elem|
200 type_class.add_member(elem.create_usage(cpp_tree))
201 end
202
203 create_Serialize(type_class,cpp_tree)
204 create_Deserialize(type_class,cpp_tree)
205 create_Zero(type_class,cpp_tree)
206 create_Size(type_class,cpp_tree)
207 create_Print(type_class,cpp_tree)
Parker Schuh711db3e2014-02-12 09:47:34 -0800208 create_GetType(type_class, cpp_tree)
209 create_DoGetType(type_class, cpp_tree)
Brian Silverman6da04272014-05-18 18:47:48 -0700210 create_DefaultConstructor(type_class, cpp_tree)
211 create_InOrderConstructor(type_class, cpp_tree)
brians343bc112013-02-10 01:53:46 +0000212
213 b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
214
brians343bc112013-02-10 01:53:46 +0000215 template = b_namespace.add_template("MessageBuilder")
brians343bc112013-02-10 01:53:46 +0000216 template.spec_args << t = @loc.to_cpp_id(@name)
brians343bc112013-02-10 01:53:46 +0000217 msg_ptr_t = "ScopedMessagePtr< #{t}>"
brians343bc112013-02-10 01:53:46 +0000218 msg_bld_t = "MessageBuilder< #{t}>"
brians343bc112013-02-10 01:53:46 +0000219 template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
brians343bc112013-02-10 01:53:46 +0000220 template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
221 template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
brians343bc112013-02-10 01:53:46 +0000222 template.add_member(:private,"friend class ::aos::Queue< #{t}>")
223
224 cons = CPP::Constructor.new(template)
Brian Silverman6da04272014-05-18 18:47:48 -0700225 template.add_member(:private,cons)
Brian Silverman08661c72013-09-01 17:24:38 -0700226 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000227 cons.args << "#{t} *msg"
brians343bc112013-02-10 01:53:46 +0000228 cons.add_cons("msg_ptr_","queue","msg")
brians343bc112013-02-10 01:53:46 +0000229 template.public
brians343bc112013-02-10 01:53:46 +0000230 DefineMembers(cpp_tree, template, msg_bld_t)
brians343bc112013-02-10 01:53:46 +0000231 end
232 def DefineMembers(cpp_tree, template, msg_bld_t)
233 send = template.def_func("bool","Send")
234 send.suite << CPP::Return.new("msg_ptr_.Send()")
235 @members.each do |elem|
236=begin
237 MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
238 double steering) {
239 msg_ptr_->steering = steering;
240 return *this;
241 }
242=end
243 setter = template.def_func(msg_bld_t,"&#{elem.name}")
244 setter.args << elem.create_usage(cpp_tree)
245 elem.set_message_builder(setter.suite)
246 setter.suite << CPP::Return.new("*this")
247
248 end
249 end
brians343bc112013-02-10 01:53:46 +0000250end
251class Target::MessageElement < Target::Node
252 attr_accessor :name,:loc,:size,:zero,:type,:printformat
253 def initialize(type,name)
254 @type,@name = type,name
255 end
Austin Schuh7e958392014-10-21 22:16:23 -0700256 def type()
257 return @type
258 end
259 def type_name(cpp_tree)
260 return type()
261 end
brians343bc112013-02-10 01:53:46 +0000262 def toPrintFormat()
263 return printformat
264 end
Austin Schuh7e958392014-10-21 22:16:23 -0700265 def create_usage(cpp_tree, this_name=nil)
266 if (this_name == nil)
267 this_name = @name
268 end
269 "#{@type} #{this_name}"
brians343bc112013-02-10 01:53:46 +0000270 end
Austin Schuh7e958392014-10-21 22:16:23 -0700271 def toNetwork(offset,suite, parent = "", this_name=nil)
272 if (this_name == nil)
273 this_name = @name
274 end
brians343bc112013-02-10 01:53:46 +0000275 suite << f_call = CPP::FuncCall.build("to_network",
Austin Schuh7e958392014-10-21 22:16:23 -0700276 "&#{parent}#{this_name}",
Brian Silverman16c82972014-02-13 15:36:40 -0800277 "&buffer[#{offset}]")
brians343bc112013-02-10 01:53:46 +0000278 f_call.args.dont_wrap = true
279 end
Austin Schuh7e958392014-10-21 22:16:23 -0700280 def toHost(offset,suite, parent = "", this_name=nil)
281 if (this_name == nil)
282 this_name = @name
283 end
brians343bc112013-02-10 01:53:46 +0000284 suite << f_call = CPP::FuncCall.build("to_host",
Brian Silverman16c82972014-02-13 15:36:40 -0800285 "&buffer[#{offset}]",
Austin Schuh7e958392014-10-21 22:16:23 -0700286 "&#{parent}#{this_name}")
brians343bc112013-02-10 01:53:46 +0000287 f_call.args.dont_wrap = true
288 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800289 def getTypeID()
Brian Silvermanff12c9f2014-03-19 17:53:29 -0700290 '0x' + ((Digest::SHA1.hexdigest(@type)[0..3].to_i(16) << 16) |
Brian Silverman1885bd02014-02-13 12:28:12 -0800291 0x2000 | # marks it as primitive
Brian Silvermanff12c9f2014-03-19 17:53:29 -0700292 size).to_s(16)
Parker Schuh711db3e2014-02-12 09:47:34 -0800293 end
294 def simpleStr()
295 "#{@type} #{@name}"
296 end
Austin Schuh7e958392014-10-21 22:16:23 -0700297 def set_message_builder(suite, this_name=nil)
298 this_name ||= @name
299 suite << "msg_ptr_->#{this_name} = #{this_name}"
brians343bc112013-02-10 01:53:46 +0000300 end
301
Austin Schuh7e958392014-10-21 22:16:23 -0700302 def zeroCall(suite, parent = "", this_name=nil)
303 if (this_name == nil)
304 this_name = @name
305 end
306 suite << CPP::Assign.new(parent + this_name,@zero)
Parker Schuh343481e2014-02-09 18:28:43 -0800307 end
Austin Schuh7e958392014-10-21 22:16:23 -0700308 def fetchPrintArgs(args, parent = "", this_name=nil)
309 if (this_name == nil)
310 this_name = @name
311 end
312 if (@type == 'bool')
313 args.push("#{parent}#{this_name} ? 'T' : 'f'")
314 elsif (@type == '::aos::time::Time')
315 args.push("AOS_TIME_ARGS(#{parent}#{this_name}.sec(), #{parent}#{this_name}.nsec())")
Parker Schuh343481e2014-02-09 18:28:43 -0800316 else
Austin Schuh7e958392014-10-21 22:16:23 -0700317 args.push("#{parent}#{this_name}")
Parker Schuh343481e2014-02-09 18:28:43 -0800318 end
brians343bc112013-02-10 01:53:46 +0000319 end
320end
321class Target::MessageArrayElement < Target::Node
Austin Schuh7e958392014-10-21 22:16:23 -0700322 attr_accessor :loc, :length
323 def initialize(type,length)
324 @type,@length = type,length
brians343bc112013-02-10 01:53:46 +0000325 end
Austin Schuh7e958392014-10-21 22:16:23 -0700326 def zero()
327 return @type.zero()
328 end
329 def name()
330 return @type.name()
331 end
332
333 def add_TypeRegister(*args)
334 if @type.respond_to?(:add_TypeRegister)
335 @type.add_TypeRegister(*args)
336 end
337 end
338
339 def toPrintFormat()
340 return ([@type.toPrintFormat] * @length).join(", ")
341 end
342 def create_usage(cpp_tree, this_name=nil)
343 if (this_name == nil)
344 this_name = name
345 end
346 return "::std::array< #{@type.type_name(cpp_tree)}, #{@length}> #{this_name}"
brians343bc112013-02-10 01:53:46 +0000347 end
348 def type()
Austin Schuh7e958392014-10-21 22:16:23 -0700349 return "::std::array< #{@type.type()}, #{@length}>"
350 end
351 def simpleStr()
352 return "#{@type.type} #{@name}[#{@length}]"
353 end
354 def getTypeID()
355 return @type.getTypeID()
brians343bc112013-02-10 01:53:46 +0000356 end
357 def size()
Austin Schuh7e958392014-10-21 22:16:23 -0700358 return @type.size * @length
brians343bc112013-02-10 01:53:46 +0000359 end
Austin Schuh7e958392014-10-21 22:16:23 -0700360 def toNetwork(offset, suite, parent="", this_name=nil)
361 if (this_name == nil)
362 this_name = name
363 end
brians343bc112013-02-10 01:53:46 +0000364 offset = (offset == 0) ? "" : "#{offset} + "
Austin Schuh7e958392014-10-21 22:16:23 -0700365 for_loop_var = getForLoopVar()
366 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
367 @type.toNetwork("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
brians343bc112013-02-10 01:53:46 +0000368 end
Austin Schuh7e958392014-10-21 22:16:23 -0700369 def toHost(offset, suite, parent="", this_name=nil)
370 if (this_name == nil)
371 this_name = name
372 end
brians343bc112013-02-10 01:53:46 +0000373 offset = (offset == 0) ? "" : "#{offset} + "
Austin Schuh7e958392014-10-21 22:16:23 -0700374 for_loop_var = getForLoopVar()
375 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
376 @type.toHost("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
brians343bc112013-02-10 01:53:46 +0000377 end
Austin Schuh7e958392014-10-21 22:16:23 -0700378 def set_message_builder(suite, this_name=nil)
379 if (this_name == nil)
380 this_name = name
381 end
382
383 for_loop_var = getForLoopVar()
384 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
385 @type.set_message_builder(for_stmt.suite, "#{this_name}[#{for_loop_var}]")
brians343bc112013-02-10 01:53:46 +0000386 end
Austin Schuh7e958392014-10-21 22:16:23 -0700387 def zeroCall(suite, parent="", this_name=nil)
388 if (this_name == nil)
389 this_name = name
390 end
391
392 offset = (offset == 0) ? "" : "#{offset} + "
393 for_loop_var = getForLoopVar()
394 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
395 @type.zeroCall(for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
396 end
397 def fetchPrintArgs(args, parent = "", this_name=nil)
398 if (this_name == nil)
399 this_name = name
400 end
401 for i in 0..(@length-1)
402 @type.fetchPrintArgs(args, parent, "#{this_name}[#{i}]")
403 end
brians343bc112013-02-10 01:53:46 +0000404 end
405end