blob: 6cf44c229e25c28f2f61114cc4841cb5f4e72e2e [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
19 fields << "new ::aos::MessageType::Field{#{tId}, #{fieldName}}"
20 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()
27 member_func.suite << ("static const ::aos::MessageType kMsgMessageType(#{id}, #{@name.inspect}, {" +
28 "#{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
33 def simpleStr()
34 return "{\n" + @members.collect() { |elem| elem.simpleStr() + "\n"}.join("") + "}"
35 end
36 def getTypeID()
37 return "0x" + (((Digest::SHA1.hexdigest(simpleStr())[0..3].to_i(16)) << 16) + size).to_s(16)
38 end
39 def add_member(member)
40 @members << member
41 end
42 def size()
43 return @size if(@size)
44 @size = 0
45 @members.each do |elem|
46 @size += elem.size
47 end
48 return @size
49 end
50end
51
52class Target::MessageDec < Target::StructBase
brians343bc112013-02-10 01:53:46 +000053 attr_accessor :name,:loc,:parent,:msg_hash
54 def initialize(name)
55 @name = name
56 @members = []
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
brians343bc112013-02-10 01:53:46 +000068 def create_Print(type_class,cpp_tree)
69 member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
70 type_class.add_member(member_func)
71 member_func.args << "char *buffer"
72 member_func.args << "size_t length"
73 member_func.const = true
74 format = "\""
75 args = []
76 @members.each do |elem|
77 format += ", "
78 format += elem.toPrintFormat()
Parker Schuh343481e2014-02-09 18:28:43 -080079 elem.fetchPrintArgs(args)
brians343bc112013-02-10 01:53:46 +000080 end
Parker Schuh343481e2014-02-09 18:28:43 -080081 format += "\""
82 member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
83 member_func.suite << "buffer += super_size"
84 member_func.suite << "length -= super_size"
85 member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
brians343bc112013-02-10 01:53:46 +000086 end
87 def create_Serialize(type_class,cpp_tree)
88 member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
89 type_class.add_member(member_func)
90 #cpp_tree.cc_file.add_funct(member_func)
91 member_func.args << "char *buffer"
92 member_func.suite << "::aos::Message::Serialize(buffer)"
93 member_func.const = true
94 offset = 0
95 @members.each do |elem|
96 elem.toNetwork(offset,member_func.suite)
97 offset += elem.size;
98 end
99 member_func.suite << "return Size()"
100 end
101 def create_Deserialize(type_class,cpp_tree)
102 member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
103 type_class.add_member(member_func)
104 #cpp_tree.cc_file.add_funct(member_func)
105 member_func.args << "const char *buffer"
106 member_func.suite << "::aos::Message::Deserialize(buffer)"
107 offset = 0
108 @members.each do |elem|
109 elem.toHost(offset,member_func.suite)
110 offset += elem.size;
111 end
112 member_func.suite << "return Size()"
113 end
114 def create_Zero(type_class,cpp_tree)
115 member_func = CPP::MemberFunc.new(type_class,"void","Zero")
116 type_class.add_member(member_func)
117 #cpp_tree.cc_file.add_funct(member_func)
118 @members.each do |elem|
119 elem.zeroCall(member_func.suite)
120 end
121 member_func.suite << "::aos::Message::Zero()"
122 end
123 def create_Size(type_class,cpp_tree)
124 member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
125 member_func.inline = true
126 member_func.static = true
127 type_class.add_member(member_func.forward_dec)
128 #cpp_tree.cc_file.add_funct(member_func)
129 size = 0
130 @members.each do |elem|
131 size += elem.size
132 end
133 member_func.suite << CPP::Return.new(CPP::Add.new(size,
134 "::aos::Message::Size()"))
135 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800136 def create_GetType(type_class, cpp_tree)
Brian Silverman665e60c2014-02-12 13:57:10 -0800137 member_func = CPP::MemberFunc.new(type_class,"const ::aos::MessageType*","GetType")
138 type_class.add_member(member_func)
139 member_func.static = true
Parker Schuh711db3e2014-02-12 09:47:34 -0800140 member_func.suite << "static ::aos::Once<const ::aos::MessageType> getter(#{type_class.name}::DoGetType)"
Brian Silverman665e60c2014-02-12 13:57:10 -0800141 member_func.suite << CPP::Return.new("getter.Get()")
Parker Schuh711db3e2014-02-12 09:47:34 -0800142 end
brians343bc112013-02-10 01:53:46 +0000143 def self.builder_loc(loc)
144 return @builder_loc if(@builder_loc)
145 return @builder_loc = loc.root.get_make("aos")
146 end
147 def type_name(builder_loc,name)
148 if(builder_loc == @loc) #use relative name
149 return name
150 else #use full name
151 return @loc.to_cpp_id(name)
152 end
153 end
154 def create(cpp_tree)
155 return self if(@extern)
156 orig_namespace = namespace = cpp_tree.get(@loc)
157 name = ""
158 if(namespace.class < Types::Type) #is nested
159 name = namespace.name + "_" + name
160 namespace = namespace.space
161 end
162 type_class = namespace.add_struct(name + @name)
163 if(name.length > 0)
164 orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
165 end
166 cpp_tree.set(self,type_class)
167 type_class.set_parent("public ::aos::Message")
Parker Schuh711db3e2014-02-12 09:47:34 -0800168 ts = self.simpleStr()
Brian Silverman8efe23e2013-07-07 23:31:37 -0700169 self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
brians343bc112013-02-10 01:53:46 +0000170 type_class.add_member("enum {kQueueLength = 1234, kHash = #{self.msg_hash}}")
171 @members.each do |elem|
172 type_class.add_member(elem.create_usage(cpp_tree))
173 end
174
175 create_Serialize(type_class,cpp_tree)
176 create_Deserialize(type_class,cpp_tree)
177 create_Zero(type_class,cpp_tree)
178 create_Size(type_class,cpp_tree)
179 create_Print(type_class,cpp_tree)
Parker Schuh711db3e2014-02-12 09:47:34 -0800180 create_GetType(type_class, cpp_tree)
181 create_DoGetType(type_class, cpp_tree)
brians343bc112013-02-10 01:53:46 +0000182
183 b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
184
185 safetemplate = Types::TemplateClass.new(b_namespace,"SafeMessageBuilder")
186 ifdef_statement = Types::PreprocessorIf.new(b_namespace,"!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)")
187 ifdef_statement.add_member(safetemplate)
188 b_namespace.add(ifdef_statement)
189 template = b_namespace.add_template("MessageBuilder")
190 safetemplate.spec_args << t = @loc.to_cpp_id(@name)
191 template.spec_args << t = @loc.to_cpp_id(@name)
192 safemsg_ptr_t = "SafeScopedMessagePtr< #{t}>"
193 msg_ptr_t = "ScopedMessagePtr< #{t}>"
194 safemsg_bld_t = "SafeMessageBuilder< #{t}>"
195 msg_bld_t = "MessageBuilder< #{t}>"
196 safetemplate.add_member(:private,"#{safemsg_ptr_t} msg_ptr_")
197 template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
brians343bc112013-02-10 01:53:46 +0000198 template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
199 template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
200 safetemplate.add_member(:private,"friend class ::aos::Queue< #{t}>")
201 template.add_member(:private,"friend class ::aos::Queue< #{t}>")
202
203 cons = CPP::Constructor.new(template)
204 unsafe_cons = CPP::Constructor.new(template)
205 cons_ifdef_statement = CPP::PreprocessorIf.new(cons, unsafe_cons)
206 cons_ifdef_statement.name = "!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)"
207 template.add_member(:private,cons_ifdef_statement)
Brian Silverman08661c72013-09-01 17:24:38 -0700208 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000209 cons.args << "#{t} *msg"
210 unsafe_cons.args << "#{t} *msg"
211 cons.add_cons("msg_ptr_","queue","msg")
212 unsafe_cons.add_cons("msg_ptr_","msg")
213 cons = safetemplate.add_member(:private,CPP::Constructor.new(safetemplate))
Brian Silverman08661c72013-09-01 17:24:38 -0700214 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000215 cons.add_cons("msg_ptr_","queue")
216 safetemplate.public
217 template.public
218 DefineMembers(cpp_tree, safetemplate, safemsg_bld_t)
219 DefineMembers(cpp_tree, template, msg_bld_t)
220
brians343bc112013-02-10 01:53:46 +0000221 end
222 def DefineMembers(cpp_tree, template, msg_bld_t)
223 send = template.def_func("bool","Send")
224 send.suite << CPP::Return.new("msg_ptr_.Send()")
225 @members.each do |elem|
226=begin
227 MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
228 double steering) {
229 msg_ptr_->steering = steering;
230 return *this;
231 }
232=end
233 setter = template.def_func(msg_bld_t,"&#{elem.name}")
234 setter.args << elem.create_usage(cpp_tree)
235 elem.set_message_builder(setter.suite)
236 setter.suite << CPP::Return.new("*this")
237
238 end
239 end
brians343bc112013-02-10 01:53:46 +0000240end
241class Target::MessageElement < Target::Node
242 attr_accessor :name,:loc,:size,:zero,:type,:printformat
243 def initialize(type,name)
244 @type,@name = type,name
245 end
246 def toPrintFormat()
247 return printformat
248 end
249 def create_usage(cpp_tree)
250 "#{@type} #{@name}"
251 end
Parker Schuh343481e2014-02-09 18:28:43 -0800252 def toNetwork(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000253 offset = (offset == 0) ? "" : "#{offset} + "
254 suite << f_call = CPP::FuncCall.build("to_network",
Parker Schuh343481e2014-02-09 18:28:43 -0800255 "&#{parent}#{@name}",
brians343bc112013-02-10 01:53:46 +0000256 "&buffer[#{offset}::aos::Message::Size()]")
257 f_call.args.dont_wrap = true
258 end
Parker Schuh343481e2014-02-09 18:28:43 -0800259 def toHost(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000260 offset = (offset == 0) ? "" : "#{offset} + "
261 suite << f_call = CPP::FuncCall.build("to_host",
262 "&buffer[#{offset}::aos::Message::Size()]",
Parker Schuh343481e2014-02-09 18:28:43 -0800263 "&#{parent}#{@name}")
brians343bc112013-02-10 01:53:46 +0000264 f_call.args.dont_wrap = true
265 end
Parker Schuh711db3e2014-02-12 09:47:34 -0800266 def getTypeID()
Brian Silverman665e60c2014-02-12 13:57:10 -0800267 Digest::SHA1.hexdigest(@type)[0..7].to_i(16) | 0x4000 #ensures is primative
Parker Schuh711db3e2014-02-12 09:47:34 -0800268 end
269 def simpleStr()
270 "#{@type} #{@name}"
271 end
brians343bc112013-02-10 01:53:46 +0000272 def set_message_builder(suite)
273 suite << "msg_ptr_->#{@name} = #{@name}"
274 end
275
Parker Schuh343481e2014-02-09 18:28:43 -0800276 def zeroCall(suite, parent = "")
277 suite << CPP::Assign.new(parent + @name,@zero)
278 end
279 def fetchPrintArgs(args, parent = "")
280 if (self.type == 'bool')
281 args.push("#{parent}#{self.name} ? 'T' : 'f'")
282 else
283 args.push("#{parent}#{self.name}")
284 end
brians343bc112013-02-10 01:53:46 +0000285 end
286end
287class Target::MessageArrayElement < Target::Node
288 attr_accessor :name,:loc,:size,:zero,:type
289 def initialize(type,name,length)
290 @type,@name,@length = type,name,length
291 end
292 def create_usage(cpp_tree)
293 "#{@type} #{@name}[#@length]"
294 end
295 def type()
296 "#{@type}[#@length]"
297 end
298 def size()
299 @size * @length
300 end
301 def toNetwork(offset,suite)
302 offset = (offset == 0) ? "" : "#{offset} + "
303 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
304 for_stmt.suite << f_call = CPP::FuncCall.build("to_network",
305 "&(#{@name}[i])",
306 "&buffer[i + #{offset}::aos::Message::Size()]")
307 f_call.args.dont_wrap = true
308 end
309 def toHost(offset,suite)
310 offset = (offset == 0) ? "" : "#{offset} + "
311 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
312 for_stmt.suite << f_call = CPP::FuncCall.build("to_host",
313 "&buffer[i + #{offset}::aos::Message::Size()]",
314 "&(#{@name}[i])")
315 f_call.args.dont_wrap = true
316 end
317 def set_message_builder(suite)
318 suite << "memcpy(msg_ptr_->#{@name},#{@name},#@length)"
319 end
320 def zeroCall(suite)
321 suite << "memset(#@name,0,#{size()})"
322 end
323end