blob: 92e32e58588cbcf4e57d0194852fe5b3d8f2bb88 [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)
9 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType* ","DoGetType")
10 member_func.static = true
11# member_func.const = true
12 fields = []
13 @members.each do |member|
14 tId = member.getTypeID()
15 fieldName = member.name.inspect
16 if(member.respond_to?(:add_TypeRegister))
17 member.add_TypeRegister(type_class, member_func)
18 end
19 fields << "new ::aos::MessageType::Field{#{tId}, #{fieldName}}"
20 end
21 id = getTypeID()
22 member_func.suite << ("static const ::aos::MessageType kMsgMessageType(#{id}, #{@name.inspect}, {" +
23 "#{fields.join(", ")}})");
24 type_class.add_member(member_func)
25# val = CPP::StaticVar.new(type_class, "const int", "asdf")
26# val.args << 0
27# type_class.add_member(val)
28 member_func.suite << "::type_cache::Add(&kMsgMessageType)"
29 member_func.suite << CPP::Return.new("&kMsgMessageType")
30 end
31 def simpleStr()
32 return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
33 end
34 def getTypeID()
35 return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) + size).to_s(16)
36 end
37 def add_member(member)
38 @members << member
39 end
40 def size()
41 return @size if(@size)
42 @size = 0
43 @members.each do |elem|
44 @size += elem.size
45 end
46 return @size
47 end
48end
49
50class Target::MessageDec < Target::StructBase
brians343bc112013-02-10 01:53:46 +000051 attr_accessor :name,:loc,:parent,:msg_hash
52 def initialize(name)
53 @name = name
54 @members = []
55 end
56 def extern=(value)
57 @extern=value
58 end
59 def get_name()
60 if(@parent)
61 return "#{@parent.get_name}.#{@name}"
62 else
63 return "#{@name}"
64 end
65 end
brians343bc112013-02-10 01:53:46 +000066 def create_Print(type_class,cpp_tree)
67 member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
68 type_class.add_member(member_func)
69 member_func.args << "char *buffer"
70 member_func.args << "size_t length"
71 member_func.const = true
72 format = "\""
73 args = []
74 @members.each do |elem|
75 format += ", "
76 format += elem.toPrintFormat()
Parker Schuh343481e2014-02-09 18:28:43 -080077 elem.fetchPrintArgs(args)
brians343bc112013-02-10 01:53:46 +000078 end
Parker Schuh343481e2014-02-09 18:28:43 -080079 format += "\""
80 member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
81 member_func.suite << "buffer += super_size"
82 member_func.suite << "length -= super_size"
83 member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
brians343bc112013-02-10 01:53:46 +000084 end
85 def create_Serialize(type_class,cpp_tree)
86 member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
87 type_class.add_member(member_func)
88 #cpp_tree.cc_file.add_funct(member_func)
89 member_func.args << "char *buffer"
90 member_func.suite << "::aos::Message::Serialize(buffer)"
91 member_func.const = true
92 offset = 0
93 @members.each do |elem|
94 elem.toNetwork(offset,member_func.suite)
95 offset += elem.size;
96 end
97 member_func.suite << "return Size()"
98 end
99 def create_Deserialize(type_class,cpp_tree)
100 member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
101 type_class.add_member(member_func)
102 #cpp_tree.cc_file.add_funct(member_func)
103 member_func.args << "const char *buffer"
104 member_func.suite << "::aos::Message::Deserialize(buffer)"
105 offset = 0
106 @members.each do |elem|
107 elem.toHost(offset,member_func.suite)
108 offset += elem.size;
109 end
110 member_func.suite << "return Size()"
111 end
112 def create_Zero(type_class,cpp_tree)
113 member_func = CPP::MemberFunc.new(type_class,"void","Zero")
114 type_class.add_member(member_func)
115 #cpp_tree.cc_file.add_funct(member_func)
116 @members.each do |elem|
117 elem.zeroCall(member_func.suite)
118 end
119 member_func.suite << "::aos::Message::Zero()"
120 end
121 def create_Size(type_class,cpp_tree)
122 member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
123 member_func.inline = true
124 member_func.static = true
125 type_class.add_member(member_func.forward_dec)
126 #cpp_tree.cc_file.add_funct(member_func)
127 size = 0
128 @members.each do |elem|
129 size += elem.size
130 end
131 member_func.suite << CPP::Return.new(CPP::Add.new(size,
132 "::aos::Message::Size()"))
133 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800134 def create_GetType(type_class, cpp_tree)
135 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType& ","GetType")
136 member_func.const = true
137 member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
138 member_func.suite << CPP::Return.new("*getter.Get()")
139 end
brians343bc112013-02-10 01:53:46 +0000140 def self.builder_loc(loc)
141 return @builder_loc if(@builder_loc)
142 return @builder_loc = loc.root.get_make("aos")
143 end
144 def type_name(builder_loc,name)
145 if(builder_loc == @loc) #use relative name
146 return name
147 else #use full name
148 return @loc.to_cpp_id(name)
149 end
150 end
151 def create(cpp_tree)
152 return self if(@extern)
153 orig_namespace = namespace = cpp_tree.get(@loc)
154 name = ""
155 if(namespace.class < Types::Type) #is nested
156 name = namespace.name + "_" + name
157 namespace = namespace.space
158 end
159 type_class = namespace.add_struct(name + @name)
160 if(name.length > 0)
161 orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
162 end
163 cpp_tree.set(self,type_class)
164 type_class.set_parent("public ::aos::Message")
Parker Schuh711db3e2014-02-12 09:47:34 -0800165 ts = self.simpleStr()
Brian Silverman8efe23e2013-07-07 23:31:37 -0700166 self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
brians343bc112013-02-10 01:53:46 +0000167 type_class.add_member("enum {kQueueLength = 1234, kHash = #{self.msg_hash}}")
168 @members.each do |elem|
169 type_class.add_member(elem.create_usage(cpp_tree))
170 end
171
172 create_Serialize(type_class,cpp_tree)
173 create_Deserialize(type_class,cpp_tree)
174 create_Zero(type_class,cpp_tree)
175 create_Size(type_class,cpp_tree)
176 create_Print(type_class,cpp_tree)
Parker Schuh711db3e2014-02-12 09:47:34 -0800177 create_GetType(type_class, cpp_tree)
178 create_DoGetType(type_class, cpp_tree)
brians343bc112013-02-10 01:53:46 +0000179
180 b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
181
182 safetemplate = Types::TemplateClass.new(b_namespace,"SafeMessageBuilder")
183 ifdef_statement = Types::PreprocessorIf.new(b_namespace,"!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)")
184 ifdef_statement.add_member(safetemplate)
185 b_namespace.add(ifdef_statement)
186 template = b_namespace.add_template("MessageBuilder")
187 safetemplate.spec_args << t = @loc.to_cpp_id(@name)
188 template.spec_args << t = @loc.to_cpp_id(@name)
189 safemsg_ptr_t = "SafeScopedMessagePtr< #{t}>"
190 msg_ptr_t = "ScopedMessagePtr< #{t}>"
191 safemsg_bld_t = "SafeMessageBuilder< #{t}>"
192 msg_bld_t = "MessageBuilder< #{t}>"
193 safetemplate.add_member(:private,"#{safemsg_ptr_t} msg_ptr_")
194 template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
195 namespace.add_pre_swig("%feature(\"valuewrapper\") #{safemsg_bld_t}")
196 template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
197 template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
198 safetemplate.add_member(:private,"friend class ::aos::Queue< #{t}>")
199 template.add_member(:private,"friend class ::aos::Queue< #{t}>")
200
201 cons = CPP::Constructor.new(template)
202 unsafe_cons = CPP::Constructor.new(template)
203 cons_ifdef_statement = CPP::PreprocessorIf.new(cons, unsafe_cons)
204 cons_ifdef_statement.name = "!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)"
205 template.add_member(:private,cons_ifdef_statement)
Brian Silverman08661c72013-09-01 17:24:38 -0700206 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000207 cons.args << "#{t} *msg"
208 unsafe_cons.args << "#{t} *msg"
209 cons.add_cons("msg_ptr_","queue","msg")
210 unsafe_cons.add_cons("msg_ptr_","msg")
211 cons = safetemplate.add_member(:private,CPP::Constructor.new(safetemplate))
Brian Silverman08661c72013-09-01 17:24:38 -0700212 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000213 cons.add_cons("msg_ptr_","queue")
214 safetemplate.public
215 template.public
216 DefineMembers(cpp_tree, safetemplate, safemsg_bld_t)
217 DefineMembers(cpp_tree, template, msg_bld_t)
218
219 java_type_name = java_type_name(cpp_tree)
220 namespace.add_post_swig("%template(#{java_type_name}) ::aos::Queue< #{t}>")
221 namespace.add_post_swig("%template(#{java_ptr_name(cpp_tree)}) ::aos::SafeScopedMessagePtr< #{t}>")
222 namespace.add_post_swig("%template(#{java_builder_name(cpp_tree)}) ::aos::SafeMessageBuilder< #{t}>")
223 # TODO(aschuh): Figure out why this doesn't work and fix it.
224 #namespace.add_post_swig("%typemap(javabase) #{@name} \"aos.Message\"")
225
226 end
227 def DefineMembers(cpp_tree, template, msg_bld_t)
228 send = template.def_func("bool","Send")
229 send.suite << CPP::Return.new("msg_ptr_.Send()")
230 @members.each do |elem|
231=begin
232 MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
233 double steering) {
234 msg_ptr_->steering = steering;
235 return *this;
236 }
237=end
238 setter = template.def_func(msg_bld_t,"&#{elem.name}")
239 setter.args << elem.create_usage(cpp_tree)
240 elem.set_message_builder(setter.suite)
241 setter.suite << CPP::Return.new("*this")
242
243 end
244 end
245 def java_ptr_name(cpp_tree)
246 return "#{@name}MessagePtr"
247 end
248 def java_builder_name(cpp_tree)
249 return "#{@name}MessageBuilder"
250 end
251 def java_type_name(cpp_tree)
252 return "#{@name}Queue"
253 end
254end
255class Target::MessageElement < Target::Node
256 attr_accessor :name,:loc,:size,:zero,:type,:printformat
257 def initialize(type,name)
258 @type,@name = type,name
259 end
260 def toPrintFormat()
261 return printformat
262 end
263 def create_usage(cpp_tree)
264 "#{@type} #{@name}"
265 end
Parker Schuh343481e2014-02-09 18:28:43 -0800266 def toNetwork(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000267 offset = (offset == 0) ? "" : "#{offset} + "
268 suite << f_call = CPP::FuncCall.build("to_network",
Parker Schuh343481e2014-02-09 18:28:43 -0800269 "&#{parent}#{@name}",
brians343bc112013-02-10 01:53:46 +0000270 "&buffer[#{offset}::aos::Message::Size()]")
271 f_call.args.dont_wrap = true
272 end
Parker Schuh343481e2014-02-09 18:28:43 -0800273 def toHost(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000274 offset = (offset == 0) ? "" : "#{offset} + "
275 suite << f_call = CPP::FuncCall.build("to_host",
276 "&buffer[#{offset}::aos::Message::Size()]",
Parker Schuh343481e2014-02-09 18:28:43 -0800277 "&#{parent}#{@name}")
brians343bc112013-02-10 01:53:46 +0000278 f_call.args.dont_wrap = true
279 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800280 def getTypeID()
281 Digest::SHA1.hexdigest(@type)[0..7].to_i(16) & 0x4000 #ensures is primative
282 end
283 def simpleStr()
284 "#{@type} #{@name}"
285 end
brians343bc112013-02-10 01:53:46 +0000286 def set_message_builder(suite)
287 suite << "msg_ptr_->#{@name} = #{@name}"
288 end
289
Parker Schuh343481e2014-02-09 18:28:43 -0800290 def zeroCall(suite, parent = "")
291 suite << CPP::Assign.new(parent + @name,@zero)
292 end
293 def fetchPrintArgs(args, parent = "")
294 if (self.type == 'bool')
295 args.push("#{parent}#{self.name} ? 'T' : 'f'")
296 else
297 args.push("#{parent}#{self.name}")
298 end
brians343bc112013-02-10 01:53:46 +0000299 end
300end
301class Target::MessageArrayElement < Target::Node
302 attr_accessor :name,:loc,:size,:zero,:type
303 def initialize(type,name,length)
304 @type,@name,@length = type,name,length
305 end
306 def create_usage(cpp_tree)
307 "#{@type} #{@name}[#@length]"
308 end
309 def type()
310 "#{@type}[#@length]"
311 end
312 def size()
313 @size * @length
314 end
315 def toNetwork(offset,suite)
316 offset = (offset == 0) ? "" : "#{offset} + "
317 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
318 for_stmt.suite << f_call = CPP::FuncCall.build("to_network",
319 "&(#{@name}[i])",
320 "&buffer[i + #{offset}::aos::Message::Size()]")
321 f_call.args.dont_wrap = true
322 end
323 def toHost(offset,suite)
324 offset = (offset == 0) ? "" : "#{offset} + "
325 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
326 for_stmt.suite << f_call = CPP::FuncCall.build("to_host",
327 "&buffer[i + #{offset}::aos::Message::Size()]",
328 "&(#{@name}[i])")
329 f_call.args.dont_wrap = true
330 end
331 def set_message_builder(suite)
332 suite << "memcpy(msg_ptr_->#{@name},#{@name},#@length)"
333 end
334 def zeroCall(suite)
335 suite << "memset(#@name,0,#{size()})"
336 end
337end