blob: 579ce0c3f6928952988c7201f1e8befb95d758f7 [file] [log] [blame]
Brian Silverman8efe23e2013-07-07 23:31:37 -07001begin
2 require "sha1"
3rescue LoadError
4 require "digest/sha1"
5end
6
brians343bc112013-02-10 01:53:46 +00007class Target::MessageDec < Target::Node
8 attr_accessor :name,:loc,:parent,:msg_hash
9 def initialize(name)
10 @name = name
11 @members = []
12 end
13 def extern=(value)
14 @extern=value
15 end
16 def get_name()
17 if(@parent)
18 return "#{@parent.get_name}.#{@name}"
19 else
20 return "#{@name}"
21 end
22 end
23 def add_member(member)
24 @members << member
25 end
26 def create_Print(type_class,cpp_tree)
27 member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
28 type_class.add_member(member_func)
29 member_func.args << "char *buffer"
30 member_func.args << "size_t length"
31 member_func.const = true
32 format = "\""
33 args = []
34 @members.each do |elem|
35 format += ", "
36 format += elem.toPrintFormat()
Parker Schuh343481e2014-02-09 18:28:43 -080037 elem.fetchPrintArgs(args)
brians343bc112013-02-10 01:53:46 +000038 end
Parker Schuh343481e2014-02-09 18:28:43 -080039 format += "\""
40 member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
41 member_func.suite << "buffer += super_size"
42 member_func.suite << "length -= super_size"
43 member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
brians343bc112013-02-10 01:53:46 +000044 end
45 def create_Serialize(type_class,cpp_tree)
46 member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
47 type_class.add_member(member_func)
48 #cpp_tree.cc_file.add_funct(member_func)
49 member_func.args << "char *buffer"
50 member_func.suite << "::aos::Message::Serialize(buffer)"
51 member_func.const = true
52 offset = 0
53 @members.each do |elem|
54 elem.toNetwork(offset,member_func.suite)
55 offset += elem.size;
56 end
57 member_func.suite << "return Size()"
58 end
59 def create_Deserialize(type_class,cpp_tree)
60 member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
61 type_class.add_member(member_func)
62 #cpp_tree.cc_file.add_funct(member_func)
63 member_func.args << "const char *buffer"
64 member_func.suite << "::aos::Message::Deserialize(buffer)"
65 offset = 0
66 @members.each do |elem|
67 elem.toHost(offset,member_func.suite)
68 offset += elem.size;
69 end
70 member_func.suite << "return Size()"
71 end
72 def create_Zero(type_class,cpp_tree)
73 member_func = CPP::MemberFunc.new(type_class,"void","Zero")
74 type_class.add_member(member_func)
75 #cpp_tree.cc_file.add_funct(member_func)
76 @members.each do |elem|
77 elem.zeroCall(member_func.suite)
78 end
79 member_func.suite << "::aos::Message::Zero()"
80 end
81 def create_Size(type_class,cpp_tree)
82 member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
83 member_func.inline = true
84 member_func.static = true
85 type_class.add_member(member_func.forward_dec)
86 #cpp_tree.cc_file.add_funct(member_func)
87 size = 0
88 @members.each do |elem|
89 size += elem.size
90 end
91 member_func.suite << CPP::Return.new(CPP::Add.new(size,
92 "::aos::Message::Size()"))
93 end
94 def self.builder_loc(loc)
95 return @builder_loc if(@builder_loc)
96 return @builder_loc = loc.root.get_make("aos")
97 end
98 def type_name(builder_loc,name)
99 if(builder_loc == @loc) #use relative name
100 return name
101 else #use full name
102 return @loc.to_cpp_id(name)
103 end
104 end
105 def create(cpp_tree)
106 return self if(@extern)
107 orig_namespace = namespace = cpp_tree.get(@loc)
108 name = ""
109 if(namespace.class < Types::Type) #is nested
110 name = namespace.name + "_" + name
111 namespace = namespace.space
112 end
113 type_class = namespace.add_struct(name + @name)
114 if(name.length > 0)
115 orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
116 end
117 cpp_tree.set(self,type_class)
118 type_class.set_parent("public ::aos::Message")
119 ts = (@members.collect { |elem|
120 elem.type + " " + elem.name
121 }).join(";")
Brian Silverman8efe23e2013-07-07 23:31:37 -0700122 self.msg_hash = "0x#{Digest::SHA1.hexdigest(ts)[-8..-1]}"
brians343bc112013-02-10 01:53:46 +0000123 type_class.add_member("enum {kQueueLength = 1234, kHash = #{self.msg_hash}}")
124 @members.each do |elem|
125 type_class.add_member(elem.create_usage(cpp_tree))
126 end
127
128 create_Serialize(type_class,cpp_tree)
129 create_Deserialize(type_class,cpp_tree)
130 create_Zero(type_class,cpp_tree)
131 create_Size(type_class,cpp_tree)
132 create_Print(type_class,cpp_tree)
133
134 b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
135
136 safetemplate = Types::TemplateClass.new(b_namespace,"SafeMessageBuilder")
137 ifdef_statement = Types::PreprocessorIf.new(b_namespace,"!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)")
138 ifdef_statement.add_member(safetemplate)
139 b_namespace.add(ifdef_statement)
140 template = b_namespace.add_template("MessageBuilder")
141 safetemplate.spec_args << t = @loc.to_cpp_id(@name)
142 template.spec_args << t = @loc.to_cpp_id(@name)
143 safemsg_ptr_t = "SafeScopedMessagePtr< #{t}>"
144 msg_ptr_t = "ScopedMessagePtr< #{t}>"
145 safemsg_bld_t = "SafeMessageBuilder< #{t}>"
146 msg_bld_t = "MessageBuilder< #{t}>"
147 safetemplate.add_member(:private,"#{safemsg_ptr_t} msg_ptr_")
148 template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
149 namespace.add_pre_swig("%feature(\"valuewrapper\") #{safemsg_bld_t}")
150 template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
151 template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
152 safetemplate.add_member(:private,"friend class ::aos::Queue< #{t}>")
153 template.add_member(:private,"friend class ::aos::Queue< #{t}>")
154
155 cons = CPP::Constructor.new(template)
156 unsafe_cons = CPP::Constructor.new(template)
157 cons_ifdef_statement = CPP::PreprocessorIf.new(cons, unsafe_cons)
158 cons_ifdef_statement.name = "!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)"
159 template.add_member(:private,cons_ifdef_statement)
Brian Silverman08661c72013-09-01 17:24:38 -0700160 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000161 cons.args << "#{t} *msg"
162 unsafe_cons.args << "#{t} *msg"
163 cons.add_cons("msg_ptr_","queue","msg")
164 unsafe_cons.add_cons("msg_ptr_","msg")
165 cons = safetemplate.add_member(:private,CPP::Constructor.new(safetemplate))
Brian Silverman08661c72013-09-01 17:24:38 -0700166 cons.args << "RawQueue *queue"
brians343bc112013-02-10 01:53:46 +0000167 cons.add_cons("msg_ptr_","queue")
168 safetemplate.public
169 template.public
170 DefineMembers(cpp_tree, safetemplate, safemsg_bld_t)
171 DefineMembers(cpp_tree, template, msg_bld_t)
172
173 java_type_name = java_type_name(cpp_tree)
174 namespace.add_post_swig("%template(#{java_type_name}) ::aos::Queue< #{t}>")
175 namespace.add_post_swig("%template(#{java_ptr_name(cpp_tree)}) ::aos::SafeScopedMessagePtr< #{t}>")
176 namespace.add_post_swig("%template(#{java_builder_name(cpp_tree)}) ::aos::SafeMessageBuilder< #{t}>")
177 # TODO(aschuh): Figure out why this doesn't work and fix it.
178 #namespace.add_post_swig("%typemap(javabase) #{@name} \"aos.Message\"")
179
180 end
181 def DefineMembers(cpp_tree, template, msg_bld_t)
182 send = template.def_func("bool","Send")
183 send.suite << CPP::Return.new("msg_ptr_.Send()")
184 @members.each do |elem|
185=begin
186 MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
187 double steering) {
188 msg_ptr_->steering = steering;
189 return *this;
190 }
191=end
192 setter = template.def_func(msg_bld_t,"&#{elem.name}")
193 setter.args << elem.create_usage(cpp_tree)
194 elem.set_message_builder(setter.suite)
195 setter.suite << CPP::Return.new("*this")
196
197 end
198 end
199 def java_ptr_name(cpp_tree)
200 return "#{@name}MessagePtr"
201 end
202 def java_builder_name(cpp_tree)
203 return "#{@name}MessageBuilder"
204 end
205 def java_type_name(cpp_tree)
206 return "#{@name}Queue"
207 end
208end
209class Target::MessageElement < Target::Node
210 attr_accessor :name,:loc,:size,:zero,:type,:printformat
211 def initialize(type,name)
212 @type,@name = type,name
213 end
214 def toPrintFormat()
215 return printformat
216 end
217 def create_usage(cpp_tree)
218 "#{@type} #{@name}"
219 end
Parker Schuh343481e2014-02-09 18:28:43 -0800220 def toNetwork(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000221 offset = (offset == 0) ? "" : "#{offset} + "
222 suite << f_call = CPP::FuncCall.build("to_network",
Parker Schuh343481e2014-02-09 18:28:43 -0800223 "&#{parent}#{@name}",
brians343bc112013-02-10 01:53:46 +0000224 "&buffer[#{offset}::aos::Message::Size()]")
225 f_call.args.dont_wrap = true
226 end
Parker Schuh343481e2014-02-09 18:28:43 -0800227 def toHost(offset,suite, parent = "")
brians343bc112013-02-10 01:53:46 +0000228 offset = (offset == 0) ? "" : "#{offset} + "
229 suite << f_call = CPP::FuncCall.build("to_host",
230 "&buffer[#{offset}::aos::Message::Size()]",
Parker Schuh343481e2014-02-09 18:28:43 -0800231 "&#{parent}#{@name}")
brians343bc112013-02-10 01:53:46 +0000232 f_call.args.dont_wrap = true
233 end
234 def set_message_builder(suite)
235 suite << "msg_ptr_->#{@name} = #{@name}"
236 end
237
Parker Schuh343481e2014-02-09 18:28:43 -0800238 def zeroCall(suite, parent = "")
239 suite << CPP::Assign.new(parent + @name,@zero)
240 end
241 def fetchPrintArgs(args, parent = "")
242 if (self.type == 'bool')
243 args.push("#{parent}#{self.name} ? 'T' : 'f'")
244 else
245 args.push("#{parent}#{self.name}")
246 end
brians343bc112013-02-10 01:53:46 +0000247 end
248end
249class Target::MessageArrayElement < Target::Node
250 attr_accessor :name,:loc,:size,:zero,:type
251 def initialize(type,name,length)
252 @type,@name,@length = type,name,length
253 end
254 def create_usage(cpp_tree)
255 "#{@type} #{@name}[#@length]"
256 end
257 def type()
258 "#{@type}[#@length]"
259 end
260 def size()
261 @size * @length
262 end
263 def toNetwork(offset,suite)
264 offset = (offset == 0) ? "" : "#{offset} + "
265 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
266 for_stmt.suite << f_call = CPP::FuncCall.build("to_network",
267 "&(#{@name}[i])",
268 "&buffer[i + #{offset}::aos::Message::Size()]")
269 f_call.args.dont_wrap = true
270 end
271 def toHost(offset,suite)
272 offset = (offset == 0) ? "" : "#{offset} + "
273 suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
274 for_stmt.suite << f_call = CPP::FuncCall.build("to_host",
275 "&buffer[i + #{offset}::aos::Message::Size()]",
276 "&(#{@name}[i])")
277 f_call.args.dont_wrap = true
278 end
279 def set_message_builder(suite)
280 suite << "memcpy(msg_ptr_->#{@name},#{@name},#@length)"
281 end
282 def zeroCall(suite)
283 suite << "memset(#@name,0,#{size()})"
284 end
285end