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