blob: 20a0c9d087c77ada5ce283331f7a51ed471365a8 [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
Brian Silverman88457ef2015-02-23 01:56:10 -05008 def create_DoGetType(type_class, cpp_tree)
9 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","DoGetType")
10 member_func.static = true
11 fields = []
Brian Silverman665e60c2014-02-12 13:57:10 -080012 register_members = []
Brian Silverman88457ef2015-02-23 01:56:10 -050013 @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)
Brian Silverman88457ef2015-02-23 01:56:10 -050018 end
19 fields << "new ::aos::MessageType::Field{#{tId}, #{member.respond_to?(:length) ? member.length : 0}, #{fieldName}}"
20 end
Brian Silverman665e60c2014-02-12 13:57:10 -080021 register_members.uniq do |member|
22 member.type
23 end.each do |member|
Brian Silverman88457ef2015-02-23 01:56:10 -050024 member.add_TypeRegister(cpp_tree, type_class, member_func)
Brian Silverman665e60c2014-02-12 13:57:10 -080025 end
Brian Silverman88457ef2015-02-23 01:56:10 -050026 id = getTypeID()
27 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}, {" +
28 "#{fields.join(", ")}})");
29 type_class.add_member(member_func)
30 member_func.suite << "::aos::type_cache::Add(kMsgMessageType)"
31 member_func.suite << CPP::Return.new("&kMsgMessageType")
32 end
33 def create_InOrderConstructor(type_class, cpp_tree)
34 if @members.empty?
35 return
36 end
37 cons = CPP::Constructor.new(type_class)
38 type_class.add_member(cons)
39 @members.each do |member|
40 if member.respond_to?(:type_name)
41 type_name = "#{member.type_name(cpp_tree)} #{member.name}_in"
42 else
43 type_name = member.create_usage(cpp_tree, "#{member.name}_in")
44 end
Brian Silverman16c82972014-02-13 15:36:40 -080045
Brian Silverman88457ef2015-02-23 01:56:10 -050046 cons.args << type_name
47 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
105 def create_EqualsNoTime(type_class,cpp_tree)
106 member_func = CPP::MemberFunc.new(type_class,"bool","EqualsNoTime")
107 member_func.const = true
108 type_class.add_member(member_func)
Comran Morshed7eaf55b2015-08-01 15:03:13 +0000109 member_func.args << "const #{type_class.name} &other"
Brian Silverman88457ef2015-02-23 01:56:10 -0500110 member_func.suite << "if (!#{type_class.parent_class}::EqualsNoTime(other)) return false;" if type_class.parent_class
111 @members.each do |elem|
112 if elem.respond_to? :create_EqualsNoTime
113 member_func.suite << "if (!other.#{elem.name}.EqualsNoTime(#{elem.name})) return false;"
Brian Silverman203a0fc2015-03-16 15:21:00 -0700114 elsif elem.respond_to?(:length) && elem.member_type.respond_to?(:create_EqualsNoTime)
115 0.upto(elem.length - 1) do |i|
116 member_func.suite << "if (!other.#{elem.name}[#{i}].EqualsNoTime(#{elem.name}[#{i}])) return false;"
117 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500118 else
119 member_func.suite << "if (other.#{elem.name} != #{elem.name}) return false;"
120 end
121 end
122 member_func.suite << CPP::Return.new('true')
123 end
124 def simpleStr()
125 return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
126 end
127 def getTypeID()
128 return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) | size).to_s(16)
129 end
130 def add_member(member)
131 @members << member
132 end
133 def size()
134 return @size if(@size)
135 @size = 0
136 @members.each do |elem|
137 @size += elem.size
138 end
139 return @size
140 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800141end
142
143class Target::MessageDec < Target::StructBase
Brian Silverman88457ef2015-02-23 01:56:10 -0500144 attr_accessor :name,:loc,:parent,:msg_hash
145 def initialize(name)
146 @name = name
147 @members = []
148 end
149 def extern=(value)
150 @extern=value
151 end
152 def get_name()
153 if(@parent)
154 return "#{@parent.get_name}.#{@name}"
155 else
156 return "#{@name}"
157 end
158 end
159 def create_Print(type_class,cpp_tree)
160 member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
161 type_class.add_member(member_func)
162 member_func.args << "char *buffer"
163 member_func.args << "size_t length"
164 member_func.const = true
165 format = "\""
166 args = []
167 @members.each do |elem|
168 format += ", "
169 format += elem.toPrintFormat()
170 elem.fetchPrintArgs(args)
171 end
Parker Schuh343481e2014-02-09 18:28:43 -0800172 format += "\""
173 member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
174 member_func.suite << "buffer += super_size"
175 member_func.suite << "length -= super_size"
Daniel Pettid5760ba2014-11-14 12:38:00 -0800176 if !args.empty?
177 member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
178 else
179 # snprintf will return zero.
180 member_func.suite << "return super_size"
181 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500182 end
183 def create_GetType(type_class, cpp_tree)
184 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","GetType")
185 type_class.add_member(member_func)
186 member_func.static = true
187 member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
188 member_func.suite << CPP::Return.new("getter.Get()")
189 end
190 def self.builder_loc(loc)
191 return @builder_loc if(@builder_loc)
192 return @builder_loc = loc.root.get_make("aos")
193 end
194 def type_name(builder_loc,name)
195 if(builder_loc == @loc) #use relative name
196 return name
197 else #use full name
198 return @loc.to_cpp_id(name)
199 end
200 end
201 def create(cpp_tree)
202 return self if(@extern)
203 orig_namespace = namespace = cpp_tree.get(@loc)
204 name = ""
205 if(namespace.class < Types::Type) #is nested
206 name = namespace.name + "_" + name
207 namespace = namespace.space
208 end
209 type_class = namespace.add_struct(name + @name)
210 if(name.length > 0)
211 orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
212 end
213 cpp_tree.set(self,type_class)
214 type_class.set_parent("public ::aos::Message")
215 ts = self.simpleStr()
216 self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
217 type_class.add_member("enum {kQueueLength = 100, kHash = #{self.msg_hash}}")
218 @members.each do |elem|
219 type_class.add_member(elem.create_usage(cpp_tree))
220 end
brians343bc112013-02-10 01:53:46 +0000221
Brian Silverman88457ef2015-02-23 01:56:10 -0500222 create_Serialize(type_class,cpp_tree)
223 create_Deserialize(type_class,cpp_tree)
224 create_Zero(type_class,cpp_tree)
225 create_Size(type_class,cpp_tree)
226 create_Print(type_class,cpp_tree)
227 create_GetType(type_class, cpp_tree)
228 create_DoGetType(type_class, cpp_tree)
229 create_DefaultConstructor(type_class, cpp_tree)
230 create_InOrderConstructor(type_class, cpp_tree)
Brian Silverman203a0fc2015-03-16 15:21:00 -0700231 create_EqualsNoTime(type_class, cpp_tree)
brians343bc112013-02-10 01:53:46 +0000232
Brian Silverman88457ef2015-02-23 01:56:10 -0500233 b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
brians343bc112013-02-10 01:53:46 +0000234
Brian Silverman88457ef2015-02-23 01:56:10 -0500235 template = b_namespace.add_template("MessageBuilder")
236 template.spec_args << t = @loc.to_cpp_id(@name)
237 msg_ptr_t = "ScopedMessagePtr< #{t}>"
238 msg_bld_t = "MessageBuilder< #{t}>"
239 template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
240 template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
241 template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
242 template.add_member(:private,"friend class ::aos::Queue< #{t}>")
brians343bc112013-02-10 01:53:46 +0000243
Brian Silverman88457ef2015-02-23 01:56:10 -0500244 cons = CPP::Constructor.new(template)
245 template.add_member(:private,cons)
246 cons.args << "RawQueue *queue"
247 cons.args << "#{t} *msg"
248 cons.add_cons("msg_ptr_","queue","msg")
249 template.public
250 DefineMembers(cpp_tree, template, msg_bld_t)
251 end
252 def DefineMembers(cpp_tree, template, msg_bld_t)
253 send = template.def_func("bool","Send")
254 send.suite << CPP::Return.new("msg_ptr_.Send()")
255 @members.each do |elem|
brians343bc112013-02-10 01:53:46 +0000256=begin
Brian Silverman88457ef2015-02-23 01:56:10 -0500257 MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
258 double steering) {
259 msg_ptr_->steering = steering;
260 return *this;
261 }
brians343bc112013-02-10 01:53:46 +0000262=end
Brian Silverman88457ef2015-02-23 01:56:10 -0500263 setter = template.def_func(msg_bld_t,"&#{elem.name}")
264 setter.args << elem.create_usage(cpp_tree)
265 elem.set_message_builder(setter.suite)
266 setter.suite << CPP::Return.new("*this")
brians343bc112013-02-10 01:53:46 +0000267
Brian Silverman88457ef2015-02-23 01:56:10 -0500268 end
269 end
brians343bc112013-02-10 01:53:46 +0000270end
271class Target::MessageElement < Target::Node
Brian Silverman88457ef2015-02-23 01:56:10 -0500272 attr_accessor :name,:loc,:size,:zero,:type,:printformat
273 def initialize(type,name)
274 @type,@name = type,name
275 end
Austin Schuh7e958392014-10-21 22:16:23 -0700276 def type()
277 return @type
278 end
279 def type_name(cpp_tree)
280 return type()
281 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500282 def toPrintFormat()
283 return printformat
284 end
285 def create_usage(cpp_tree, this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700286 if (this_name == nil)
287 this_name = @name
288 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500289 "#{@type} #{this_name}"
290 end
291 def toNetwork(offset,suite, parent = "", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700292 if (this_name == nil)
293 this_name = @name
294 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500295 suite << f_call = CPP::FuncCall.build("to_network",
296 "&#{parent}#{this_name}",
297 "&buffer[#{offset}]")
298 f_call.args.dont_wrap = true
299 end
300 def toHost(offset,suite, parent = "", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700301 if (this_name == nil)
302 this_name = @name
303 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500304 suite << f_call = CPP::FuncCall.build("to_host",
305 "&buffer[#{offset}]",
306 "&#{parent}#{this_name}")
307 f_call.args.dont_wrap = true
308 end
309 def getTypeID()
310 '0x' + ((Digest::SHA1.hexdigest(@type)[0..3].to_i(16) << 16) |
311 0x2000 | # marks it as primitive
312 size).to_s(16)
313 end
314 def simpleStr()
315 "#{@type} #{@name}"
316 end
317 def set_message_builder(suite, this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700318 this_name ||= @name
Brian Silverman88457ef2015-02-23 01:56:10 -0500319 suite << "msg_ptr_->#{this_name} = #{this_name}"
320 end
brians343bc112013-02-10 01:53:46 +0000321
Brian Silverman88457ef2015-02-23 01:56:10 -0500322 def zeroCall(suite, parent = "", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700323 if (this_name == nil)
324 this_name = @name
325 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500326 suite << CPP::Assign.new(parent + this_name,@zero)
327 end
328 def fetchPrintArgs(args, parent = "", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700329 if (this_name == nil)
330 this_name = @name
331 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500332 if (@type == 'bool')
333 args.push("#{parent}#{this_name} ? 'T' : 'f'")
Austin Schuhbccac532016-12-10 13:51:35 -0800334 elsif (@type == '::aos::monotonic_clock::time_point')
335 args.push(["AOS_TIME_ARGS(static_cast<int32_t>(",
336 "::std::chrono::duration_cast<::std::chrono::seconds>(",
337 "#{parent}#{this_name}.time_since_epoch()).count()), ",
338 "static_cast<int32_t>(::std::chrono::duration_cast<::std::chrono::nanoseconds>(",
339 "#{parent}#{this_name}.time_since_epoch() - ",
340 "::std::chrono::duration_cast<::std::chrono::seconds>(",
341 "#{parent}#{this_name}.time_since_epoch())).count()))"].join(''))
Brian Silverman88457ef2015-02-23 01:56:10 -0500342 else
343 args.push("#{parent}#{this_name}")
344 end
345 end
brians343bc112013-02-10 01:53:46 +0000346end
347class Target::MessageArrayElement < Target::Node
Brian Silverman88457ef2015-02-23 01:56:10 -0500348 attr_accessor :loc, :length
349 def initialize(type,length)
350 @type,@length = type,length
351 end
Austin Schuh7e958392014-10-21 22:16:23 -0700352 def zero()
353 return @type.zero()
354 end
355 def name()
356 return @type.name()
357 end
358
359 def add_TypeRegister(*args)
360 if @type.respond_to?(:add_TypeRegister)
361 @type.add_TypeRegister(*args)
362 end
363 end
364
Brian Silverman88457ef2015-02-23 01:56:10 -0500365 def toPrintFormat()
366 return ([@type.toPrintFormat] * @length).join(", ")
367 end
368 def create_usage(cpp_tree, this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700369 if (this_name == nil)
370 this_name = name
371 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500372 return "::std::array< #{@type.type_name(cpp_tree)}, #{@length}> #{this_name}"
373 end
374 def type()
375 return "::std::array< #{@type.type()}, #{@length}>"
376 end
Brian Silverman203a0fc2015-03-16 15:21:00 -0700377 def member_type()
378 return @type
379 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500380 def simpleStr()
381 return "#{@type.type} #{@name}[#{@length}]"
382 end
383 def getTypeID()
Austin Schuh7e958392014-10-21 22:16:23 -0700384 return @type.getTypeID()
Brian Silverman88457ef2015-02-23 01:56:10 -0500385 end
386 def size()
387 return @type.size * @length
388 end
389 def toNetwork(offset, suite, parent="", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700390 if (this_name == nil)
391 this_name = name
392 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500393 offset = (offset == 0) ? "" : "#{offset} + "
Austin Schuh7e958392014-10-21 22:16:23 -0700394 for_loop_var = getForLoopVar()
Brian Silverman88457ef2015-02-23 01:56:10 -0500395 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
396 @type.toNetwork("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
397 end
398 def toHost(offset, suite, parent="", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700399 if (this_name == nil)
400 this_name = name
401 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500402 offset = (offset == 0) ? "" : "#{offset} + "
Austin Schuh7e958392014-10-21 22:16:23 -0700403 for_loop_var = getForLoopVar()
Brian Silverman88457ef2015-02-23 01:56:10 -0500404 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
405 @type.toHost("#{offset} (#{for_loop_var} * #{@type.size})", for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
406 end
407 def set_message_builder(suite, this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700408 if (this_name == nil)
409 this_name = name
410 end
411
412 for_loop_var = getForLoopVar()
Brian Silverman88457ef2015-02-23 01:56:10 -0500413 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
414 @type.set_message_builder(for_stmt.suite, "#{this_name}[#{for_loop_var}]")
415 end
416 def zeroCall(suite, parent="", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700417 if (this_name == nil)
418 this_name = name
419 end
420
Brian Silverman88457ef2015-02-23 01:56:10 -0500421 offset = (offset == 0) ? "" : "#{offset} + "
Austin Schuh7e958392014-10-21 22:16:23 -0700422 for_loop_var = getForLoopVar()
Brian Silverman88457ef2015-02-23 01:56:10 -0500423 suite << for_stmt = CPP::For.new("int #{for_loop_var} = 0","#{for_loop_var} < #{@length}","#{for_loop_var}++")
424 @type.zeroCall(for_stmt.suite, parent, "#{this_name}[#{for_loop_var}]")
425 end
426 def fetchPrintArgs(args, parent = "", this_name=nil)
Austin Schuh7e958392014-10-21 22:16:23 -0700427 if (this_name == nil)
428 this_name = name
429 end
430 for i in 0..(@length-1)
Brian Silverman88457ef2015-02-23 01:56:10 -0500431 @type.fetchPrintArgs(args, parent, "#{this_name}[#{i}]")
Austin Schuh7e958392014-10-21 22:16:23 -0700432 end
Brian Silverman88457ef2015-02-23 01:56:10 -0500433 end
brians343bc112013-02-10 01:53:46 +0000434end