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