copied everything over from 2012 and removed all of the actual robot code except the drivetrain stuff
git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4078 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/aos/build/queues/compiler.rb b/aos/build/queues/compiler.rb
new file mode 100644
index 0000000..aef5cbf
--- /dev/null
+++ b/aos/build/queues/compiler.rb
@@ -0,0 +1,151 @@
+["tokenizer.rb","q_file.rb","queue_group.rb","queue.rb","namespaces.rb",
+"interface.rb","errors.rb"].each do |name|
+ require File.dirname(__FILE__) + "/objects/" + name
+end
+["standard_types.rb","auto_gen.rb","file_pair_types.rb",
+"dep_file_pair.rb","swig.rb"].each do |name|
+ require File.dirname(__FILE__) + "/cpp_pretty_print/" + name
+end
+["q_file.rb","message_dec.rb","queue_dec.rb"].each do |name|
+ require File.dirname(__FILE__) + "/output/" + name
+end
+require "fileutils"
+require "pathname"
+
+def parse_args(globals,args)
+ i = 0
+ $swig = false
+ $swigccout_path = ""
+ while(i < args.length)
+ if(args[i] == "-I")
+ args.delete_at(i)
+ if(!args[i])
+ $stderr.puts "hey! -I is followed by nothing."
+ $stderr.puts "\tnot a supported usage..."
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+ path = args.delete_at(i)
+ globals.add_path(path)
+ elsif(args[i] == "--swigccout")
+ args.delete_at(i)
+ $swigccout_path = args.delete_at(i)
+ elsif(args[i] == "-cpp_out")
+ args.delete_at(i)
+ path = args.delete_at(i)
+ if(path =~ /\./)
+ $stderr.puts "hey! path #{path} has a \".\" char which is "
+ $stderr.puts "\tnot a supported usage..."
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ elsif(!path)
+ $stderr.puts "hey! No cpp_out path provided."
+ $stderr.puts "\tumm, you could try -cpp_out \"\""
+ $stderr.puts "\tThat might do the trick"
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+ $cpp_out = path.split(/\\|\//)
+ elsif(args[i] == "--swig")
+ $swig = true
+ args.delete_at(i)
+ elsif(args[i] == "-cpp_base")
+ args.delete_at(i)
+ path = args.delete_at(i)
+ $cpp_base = File.expand_path(path)
+ if(!File.exists?($cpp_base))
+ $stderr.puts "output directory #{$cpp_base.inspect} does not exist."
+ $stderr.puts "\tI'm not going to make that! sheesh, who do you think I am?"
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+ elsif(args[i] =~ /^-/)
+ $stderr.puts "hey! unknown argument #{args[i]}."
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ else
+ i += 1
+ end
+ end
+ if(!$cpp_base)
+ $stderr.puts "hey! missing -cpp_base argument."
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+ if(!$cpp_out)
+ $stderr.puts "hey! missing -cpp_out argument."
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+end
+def build(filename,globals_template)
+ globals = Globals.new()
+ globals_template.paths.each do |path|
+ globals.add_path(path)
+ end
+ filename = File.expand_path(filename)
+ q_file = QFile.parse(filename)
+ output_file = q_file.q_eval(globals)
+ q_filename = File.basename(filename)
+ rel_path = ($cpp_out + [q_filename]).join("/")
+
+ FileUtils.mkdir_p(Pathname.new($cpp_base) + $cpp_out.join("/"))
+
+ cpp_tree = output_file.make_cpp_tree(rel_path)
+
+ h_file_path = $cpp_base + "/" + rel_path + ".h"
+ cc_file_path = $cpp_base + "/" + rel_path + ".cc"
+ swig_file_path = $cpp_base + "/" + rel_path + ".swig"
+ java_directory = $cpp_base + "/" + rel_path + "_java/"
+ cpp_tree.add_cc_include((rel_path + ".h").inspect)
+ cpp_tree.add_cc_include("aos/common/byteorder.h".inspect)
+ cpp_tree.add_cc_include("aos/common/inttypes.h".inspect)
+ cpp_tree.add_cc_using("::aos::to_network")
+ cpp_tree.add_cc_using("::aos::to_host")
+ cpp_tree.add_swig_header_include("aos/common/queue.h".inspect)
+ cpp_tree.add_swig_body_include("aos/atom_code/queue-tmpl.h".inspect)
+ cpp_tree.add_swig_header_include("aos/common/time.h".inspect)
+ cpp_tree.add_swig_include((rel_path + ".h").inspect)
+
+ header_file = File.open(h_file_path,"w+")
+ cc_file = File.open(cc_file_path,"w+")
+ cpp_tree.write_header_file($cpp_base,header_file)
+ cpp_tree.write_cc_file($cpp_base,cc_file)
+ cc_file.close()
+ header_file.close()
+ if ($swig)
+ swig_file = File.open(swig_file_path,"w+")
+ cpp_tree.write_swig_file($cpp_base,swig_file,q_filename)
+ swig_file.close()
+ namespace = q_file.namespace.get_name()[1..-1]
+ FileUtils.mkdir_p(java_directory)
+ includes = globals.paths.collect { |a| "-I#{a}" }
+
+ if (!system('/usr/bin/swig', *(includes + ['-I' + $cpp_base + '/',
+ '-package', namespace,
+ '-outdir', java_directory,
+ '-o', $swigccout_path,
+ '-c++', '-Wall', '-Wextra', '-java', swig_file_path])))
+ puts "Swig failed."
+ exit -1
+ end
+ end
+end
+begin
+ args = ARGV.dup
+ globals = Globals.new()
+ parse_args(globals,args)
+ if(args.length == 0)
+ $stderr.puts "hey! you want me to do something,"
+ $stderr.puts "\tbut you gave me no q files to build!"
+ $stderr.puts "\tWot. Wot."
+ exit!(-1)
+ end
+ args.each do |filename|
+ build(filename,globals)
+ end
+ exit(0)
+rescue QError => e
+ $stderr.print(e.to_s)
+ exit!(-1)
+end
diff --git a/aos/build/queues/cpp_pretty_print/auto_gen.rb b/aos/build/queues/cpp_pretty_print/auto_gen.rb
new file mode 100644
index 0000000..633c7c0
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/auto_gen.rb
@@ -0,0 +1,282 @@
+module CPP
+end
+class CPP::Comment
+ def initialize(text)
+ @text = text
+ end
+ def pp(state)
+ state.needs_semi = false
+ if(@text.include?("\n"))
+ state.print("/* #{@text} */")
+ else
+ state.print("// #{@text}")
+ end
+ end
+end
+class CPP::TODO < CPP::Comment
+ def initialize(owner,text)
+ @text = "TODO(#{owner}): #{text}"
+ end
+end
+class CPP::MemberFunc
+ class ForwardDec
+ def initialize(func) ; @func = func ; end
+ def pp(state) ; @func.pp_forward_dec(state) ; end
+ end
+ attr_accessor :args,:suite,:return_type,:name,:pre_func_types,:const,:static,:virtual
+ def initialize(type_class,return_type,name)
+ @type_class = type_class
+ @return_type = return_type
+ @name = name
+ @const = false
+ @static = false
+ @virtual = false
+ @args = CPP::Args.new()
+ @suite = CPP::Suite.new()
+ end
+ attr_accessor :inline
+ def forward_dec() ; ForwardDec.new(self) ; end
+ def pp_forward_dec(state)
+ return self.pp_inline(state) if(@inline)
+ if (@static)
+ state.print("static ")
+ elsif (@virtual)
+ state.print("virtual ")
+ end
+ state.print("#{@return_type} #{@pre_func_types}#{@name}(")
+ state.pp(@args)
+ state.print(")")
+ if (@const)
+ state.print(" const")
+ end
+ end
+ def pp_inline(state)
+ if (@static)
+ state.print("static ")
+ elsif (@virtual)
+ state.print("virtual ")
+ end
+ state.print("#{@return_type} #{@pre_func_types}#{@name}(")
+ state.pp(@args)
+ state.print(") ")
+ if (@const)
+ state.print(" const")
+ end
+ @suite.pp_one_line(state)
+ end
+ def pp(state)
+ return if(@inline)
+ state.print("#{@return_type} #{@pre_func_types}#{@type_class.chop_method_prefix}#{@name}(")
+ state.pp(@args)
+ state.print(") ")
+ if (@const)
+ state.print("const ")
+ end
+ state.pp(@suite)
+ state.v_pad(2)
+ end
+ def pp_pre_swig_file(state)
+ end
+ def pp_post_swig_file(state)
+ end
+ alias_method :pp_header_file, :pp_forward_dec
+ alias_method :pp_cc_file, :pp
+
+end
+class CPP::Constructor
+ class ForwardDec
+ def initialize(func) ; @func = func ; end
+ def pp(state) ; @func.pp_forward_dec(state) ; end
+ end
+ attr_accessor :args,:suite,:return_type,:name
+ def initialize(type_class)
+ @type_class = type_class
+ @args = CPP::Args.new()
+ @suite = CPP::Suite.new()
+ @var_cons = CPP::Args.new()
+ end
+ def forward_dec() ; ForwardDec.new(self) ; end
+ def add_cons(*args)
+ @var_cons.push(CPP::FuncCall.build(*args))
+ end
+ def pp_forward_dec(state)
+ state.print("#{@type_class.name}(")
+ state.pp(@args)
+ state.print(")")
+ end
+ def pp_inline(state)
+ pp(state,false)
+ end
+ def pp(state,prefix = true)
+ state.needs_semi = false
+ state.print(@type_class.chop_method_prefix) if(prefix)
+ state.print("#{@type_class.name}(")
+ state.pp(@args)
+ if(@var_cons.length >= 1)
+ state.print(")")
+ state.endline()
+ state.indent += 4
+ state.print(": ")
+ state.pp(@var_cons)
+ state.indent -= 4
+ state.print(" ")
+ else
+ state.print(") ")
+ end
+ state.pp(@suite)
+ state.v_pad(2)
+ end
+ alias_method :pp_header_file, :pp_forward_dec
+ alias_method :pp_cc_file, :pp
+end
+class CPP::Destructor
+ class ForwardDec
+ def initialize(func) ; @func = func ; end
+ def pp(state) ; @func.pp_forward_dec(state) ; end
+ end
+ attr_accessor :args,:suite,:return_type,:name
+ def initialize(type_class)
+ @type_class = type_class
+ @args = CPP::Args.new()
+ @suite = CPP::Suite.new()
+ end
+ def forward_dec() ; ForwardDec.new(self) ; end
+ def pp_forward_dec(state)
+ state.print("~#{@type_class.name}(")
+ state.pp(@args)
+ state.print(")")
+ end
+ def pp(state)
+ state.print("#{@type_class.chop_method_prefix}~#{@type_class.name}(")
+ state.pp(@args)
+ state.print(") ")
+ state.pp(@suite)
+ state.v_pad(2)
+ end
+ alias_method :pp_header_file, :pp_forward_dec
+ alias_method :pp_cc_file, :pp
+end
+class CPP::Include
+ attr_accessor :filename
+ def initialize(filename)
+ @filename = filename
+ end
+ def pp(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#include #{@filename}")
+ state.endline()
+ end
+end
+class CPP::IncludeGuard
+ attr_accessor :name,:suite
+ def initialize(suite = CPP::Suite.new())
+ @suite = suite
+ end
+ def self.rand_name(len = 40)
+ str = ""
+ len.times { str += ((rand(26) + ?A).chr)}
+ return str
+ end
+ def pp(state)
+ @name ||= IncludeGuard.rand_name
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#ifndef #{@name}")
+ state.endline()
+ state.suppress_indent()
+ state.print("#define #{@name}")
+ state.endline()
+ if(@suite.respond_to?(:pp_no_braces))
+ @suite.pp_no_braces(state)
+ else
+ state.pp(@suite)
+ end
+ state.endline()
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#endif // #{@name}")
+ state.endline()
+ end
+end
+class CPP::IfnDef
+ attr_accessor :name,:suite
+ def initialize(suite = CPP::Suite.new())
+ @suite = suite
+ end
+ def pp(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#ifndef #{@name}")
+ state.endline()
+ if(@suite.respond_to?(:pp_no_braces))
+ @suite.pp_no_braces(state)
+ else
+ state.pp(@suite)
+ end
+ state.endline()
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#endif // #{@name}")
+ state.endline()
+ end
+end
+class CPP::PreprocessorIf
+ attr_accessor :name,:suite
+ def initialize(ifsuite, elsesuite)
+ @ifsuite = ifsuite
+ @elsesuite = elsesuite
+ end
+ def write_if(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#if #{@name}")
+ state.endline()
+ end
+ def write_else(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#else // #{@name}")
+ state.endline()
+ end
+ def write_endif(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("#endif // #{@name}")
+ state.endline()
+ end
+ def pp_inline(state)
+ self.write_if(state)
+ @ifsuite.pp_inline(state)
+ if(@elsesuite != nil)
+ self.write_else(state)
+ @elsesuite.pp_inline(state)
+ end
+ self.write_endif(state)
+ end
+ def pp(state)
+ self.write_if(state)
+ if(@ifsuite.respond_to?(:pp_no_braces))
+ @ifsuite.pp_no_braces(state)
+ else
+ state.pp(@ifsuite)
+ end
+ if(@elsesuite != nil)
+ self.write_else(state)
+ if(@elsesuite.respond_to?(:pp_no_braces))
+ @elsesuite.pp_no_braces(state)
+ else
+ state.pp(@elsesuite)
+ end
+ end
+ self.write_endif(state)
+ end
+end
+class CPP::Using
+ def initialize(using)
+ @using = using
+ end
+ def pp(state)
+ state.print("using #{@using}")
+ end
+end
diff --git a/aos/build/queues/cpp_pretty_print/dep_file_pair.rb b/aos/build/queues/cpp_pretty_print/dep_file_pair.rb
new file mode 100644
index 0000000..571d9e0
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/dep_file_pair.rb
@@ -0,0 +1,617 @@
+class GroupElement
+ def add_group_dep(group_dep)
+ @group_dep = group_dep
+ end
+ def adjust_group(state,old_group)
+ if(@group_dep != old_group)
+ @group_dep.adjust_from(state,old_group)
+ end
+ return @group_dep
+ end
+end
+class DepMask < GroupElement
+ def initialize(elem)
+ @elem = elem
+ @deps = []
+ end
+ def add_dep(dep)
+ @deps << dep
+ self
+ end
+ def method_missing(method,*args,&blk)
+ @elem.send(method,*args,&blk)
+ end
+ alias_method :old_respond_to, :respond_to?
+ def respond_to?(method)
+ old_respond_to(method) || @elem.respond_to?(method)
+ end
+end
+
+class MemberElementHeader < GroupElement
+ def initialize(elem)
+ @elem = elem
+ end
+ def pp(state)
+ if(@elem.respond_to?(:pp_header_file))
+ @elem.pp_header_file(state)
+ else
+ state.pp(@elem)
+ end
+ end
+ def self.check(plan,elem)
+ plan.push(self.new(elem))
+ end
+end
+class MemberElementInline < GroupElement
+ def initialize(elem)
+ @elem = elem
+ end
+ def pp(state)
+ if(@elem.respond_to?(:pp_inline))
+ @elem.pp_inline(state)
+ else
+ state.pp(@elem)
+ end
+ end
+end
+class MemberElementPreSWIG < GroupElement
+ def initialize(elem)
+ @elem = elem
+ end
+ def pp(state)
+ if(@elem.respond_to?(:pp_pre_swig_file))
+ @elem.pp_pre_swig_file(state)
+ else
+ state.pp(@elem)
+ end
+ end
+ def self.check(plan,elem)
+ plan.push(self.new(elem)) if(elem.respond_to?(:pp_pre_swig_file))
+ end
+end
+class MemberElementPostSWIG < GroupElement
+ def initialize(elem)
+ @elem = elem
+ end
+ def pp(state)
+ if(@elem.respond_to?(:pp_post_swig_file))
+ @elem.pp_post_swig_file(state)
+ else
+ state.pp(@elem)
+ end
+ end
+ def self.check(plan,elem)
+ plan.push(self.new(elem)) if(elem.respond_to?(:pp_post_swig_file))
+ end
+end
+class MemberElementCC < GroupElement
+ attr_accessor :pp_override
+ def initialize(elem)
+ @elem = elem
+ end
+ def pp(state)
+ return state.pp(@elem) if(@pp_override)
+ @elem.pp_cc_file(state)
+ end
+ def self.check(plan,elem)
+ plan.push(self.new(elem)) if(elem.respond_to?(:pp_cc_file))
+ end
+end
+class ImplicitName
+ attr_accessor :parent
+ def initialize(name,parent)
+ @name = name
+ @parent = parent
+ end
+ def close(state)
+ state.endline()
+ state.needs_semi = false
+ state.print("} // namespace #{@name}\n")
+ end
+ def name()
+ if(@parent)
+ return @parent.name + "." + @name
+ else
+ return "." + @name
+ end
+ end
+ def open(state)
+ state.endline()
+ state.needs_semi = false
+ state.print("namespace #{@name} {\n")
+ end
+ def adjust_from(state,old_group)
+ close_grps = []
+ grp = old_group
+ while(grp)
+ close_grps << grp
+ grp = grp.parent
+ end
+ open_grps = []
+ grp = self
+ while(grp)
+ open_grps << grp
+ grp = grp.parent
+ end
+ while(open_grps[-1] == close_grps[-1] && close_grps[-1])
+ close_grps.pop()
+ open_grps.pop()
+ end
+ close_grps.each do |grp|
+ grp.close(state)
+ end
+ open_grps.reverse.each do |grp|
+ grp.open(state)
+ end
+ end
+ def adjust_to(state,new_group)
+ grp = self
+ while(grp)
+ grp.close(state)
+ grp = grp.parent
+ end
+ end
+end
+class GroupPlan < GroupElement
+ attr_accessor :implicit
+ def initialize(group_elem,members = [])
+ @group_elem = group_elem
+ @members = CPP::Suite.new(members)
+ end
+ def push(mem)
+ mem.add_group_dep(@implicit) if(@implicit)
+ @members << mem
+ end
+ def pp(state)
+ if(@group_elem)
+ @group_elem.open(state)
+ end
+ group = nil
+ @members.each do |member|
+ group = member.adjust_group(state,group)
+ #puts "at:#{group.name}" if(group.respond_to?(:name))
+ state.endline()
+ state.needs_semi = true
+ state.pp(member)
+ state.endline()
+ end
+ group.adjust_to(state,nil) if(group)
+ if(@group_elem)
+ @group_elem.close(state)
+ end
+ end
+end
+class SWIGPre_Mask
+ def initialize(elem)
+ @elem = elem
+ end
+ def plan_cc(plan)
+ end
+ def plan_pre_swig(plan)
+ elem = MemberElementPreSWIG.new(@elem)
+ plan.push(elem)
+ end
+ def plan_post_swig(plan)
+ end
+ def plan_header(plan);
+ end
+end
+class SWIGPost_Mask
+ def initialize(elem)
+ @elem = elem
+ end
+ def plan_cc(plan)
+ end
+ def plan_pre_swig(plan)
+ end
+ def plan_post_swig(plan)
+ elem = MemberElementPostSWIG.new(@elem)
+ plan.push(elem)
+ end
+ def plan_header(plan);
+ end
+end
+class CC_Mask
+ def initialize(elem)
+ @elem = elem
+ end
+ def plan_cc(plan)
+ elem = MemberElementCC.new(@elem)
+ elem.pp_override = true
+ plan.push(elem)
+ end
+ def plan_header(plan);
+ end
+ def plan_pre_swig(plan);
+ end
+ def plan_post_swig(plan);
+ end
+end
+module Types
+ class TypeDef
+ def initialize(type,name)
+ @type = type
+ @name = name
+ end
+ def pp(state)
+ state.pp("typedef #{@type.name} #{@name}")
+ end
+ end
+ class Type
+ attr_accessor :name,:static,:dec,:space
+ def initialize(namespace,name)
+ @space = namespace
+ @name = name
+ @members = []
+ @protections = {}
+ @deps = []
+ end
+ class ProtectionGroup
+ def initialize(name)
+ @name = name
+ end
+ def adjust_from(state,other)
+ state.indent -= 1
+ state.pp("#@name:")
+ state.endline
+ state.indent += 1
+ end
+ def adjust_to(state,other)
+ other.adjust_from(state,self) if other
+ end
+ end
+ ProtectionGroups = { :public => ProtectionGroup.new(:public),
+ :protected => ProtectionGroup.new(:protected),
+ :private => ProtectionGroup.new(:private)}
+ def set_parent(parent)
+ @parent = parent
+ end
+ def chop_method_prefix()
+ @space.chop_method_prefix + "#@name::"
+ end
+ def def_func(*args)
+ func = CPP::MemberFunc.new(self,*args)
+ @protections[func] = @protection
+ @members << func
+ return func
+ end
+ def add_cc_comment(*args)
+ args.each do |arg|
+ @members.push(CC_Mask.new(CPP::Comment.new(arg)))
+ end
+ end
+ def add_pre_swig(arg)
+ @members.push(SWIGPre_Mask.new(arg))
+ end
+ def add_post_swig(arg)
+ @members.push(SWIGPost_Mask.new(arg))
+ end
+ def plan_pre_swig(plan)
+ @members.each do |member|
+ if(member.respond_to?(:plan_pre_swig))
+ member.plan_pre_swig(plan)
+ elsif(member.respond_to?(:pp_pre_swig_file))
+ plan.push(MemberElementPreSWIG.new(member))
+ end
+ end
+ end
+ def plan_post_swig(plan)
+ @members.each do |member|
+ if(member.respond_to?(:plan_post_swig))
+ member.plan_post_swig(plan)
+ elsif(member.respond_to?(:pp_post_swig_file))
+ plan.push(MemberElementPostSWIG.new(member))
+ end
+ end
+ end
+ def plan_cc(plan)
+ @members.each do |member|
+ if(member.respond_to?(:plan_cc))
+ member.plan_cc(plan)
+ elsif(member.respond_to?(:pp_cc_file))
+ plan.push(MemberElementCC.new(member))
+ end
+ end
+ end
+ def plan_header(plan)
+ group_plan = GroupPlan.new(self)
+ plan.push(group_plan)
+ @members.each do |member|
+ group_plan.implicit = ProtectionGroups[@protections[member]]
+ if(member.respond_to?(:plan_header))
+ member.plan_header(group_plan)
+ else
+ group_plan.push(MemberElementHeader.new(member))
+ end
+ #member.plan_cc(plan)
+ end
+ end
+ def open(state)
+ state.needs_semi = false
+ state.v_pad(2)
+ if(@static)
+ state.print("static ")
+ end
+ self.template_header(state) if(self.respond_to?(:template_header))
+ state.print("#{self.class.type_name} #{@name}")
+ self.template_spec_args(state) if(self.respond_to?(:template_spec_args))
+ if(@parent)
+ state.print(" : #{@parent} {\n")
+ else
+ state.pp(" {\n")
+ end
+ state.indent += 2
+ end
+ def close(state)
+ state.indent -= 2
+ state.needs_semi = true
+ if(@dec)
+ state.print("\n} #{@dec}")
+ else
+ state.print("\n}")
+ end
+ state.v_pad(2)
+ end
+ def add_dep(other)
+ @deps << other
+ self
+ end
+ end
+ class Class < Type
+ def add_member(protection,member)
+ @protection = protection
+ @members.push(member)
+ @protections[member] = protection
+ return member
+ end
+ def add_struct(*args)
+ add_member(:public, Types::Struct.new(self,*args))
+ end
+ def public() ; @protection = :public ; end
+ def protected() ; @protection = :protected ; end
+ def private() ; @protection = :private ; end
+ def self.type_name() ; "class" ; end
+ end
+ class PreprocessorIf < Type
+ def initialize(*args)
+ super(*args)
+ end
+ def add_member(member)
+ @members.push(member)
+ return member
+ end
+ def self.type_name() ; "#if" ; end
+ def open(state)
+ state.needs_semi = false
+ state.print("\n#if #{@name}")
+ end
+ def close(state)
+ state.needs_semi = false
+ state.print("\n#endif // #{@name}")
+ end
+ end
+ class Struct < Type
+ def add_member(member)
+ @members.push(member)
+ return member
+ end
+ def self.type_name() ; "struct" ; end
+ end
+ class TemplateClass < Class
+ def initialize(*args)
+ super(*args)
+ @t_args = CPP::Args.new()
+ end
+ def spec_args()
+ return @spec_args ||= CPP::Args.new()
+ end
+ def template_header(state)
+ if(@t_args.length > 0)
+ state.pp("template < ")
+ state.pp(@t_args)
+ else
+ state.pp("template <")
+ end
+ state.pp(">\n")
+ end
+ def plan_cc(plan)
+
+ end
+ def plan_header(plan)
+ group_plan = GroupPlan.new(self)
+ plan.push(group_plan)
+ @members.each do |member|
+ group_plan.implicit = ProtectionGroups[@protections[member]]
+ if(member.respond_to?(:plan_header))
+ member.plan_header(group_plan)
+ else
+ group_plan.push(MemberElementInline.new(member))
+ end
+ end
+ end
+ def template_spec_args(state)
+ if(@spec_args)
+ state.pp("< ")
+ state.pp(@spec_args)
+ state.pp(">")
+ end
+ end
+ end
+end
+class DepFilePair
+ class NameSpace
+ def initialize(name,parent)
+ @name,@parent = name,parent
+ @members = []
+ end
+ def add_struct(*args)
+ add Types::Struct.new(self,*args)
+ end
+ def add_template(*args)
+ add Types::TemplateClass.new(self,*args)
+ end
+ def add_class(*args)
+ add Types::Class.new(self,*args)
+ end
+ def add_cc(arg)
+ @members.push(CC_Mask.new(arg))
+ end
+ def add_pre_swig(arg)
+ @members.push(SWIGPre_Mask.new(arg))
+ end
+ def add_post_swig(arg)
+ @members.push(SWIGPost_Mask.new(arg))
+ end
+ def chop_method_prefix()
+ ""
+ end
+ def class_comment(*args)
+ add CPP::Comment.new(*args)
+ end
+ def var_dec_comment(*args)
+ add CPP::Comment.new(*args)
+ end
+ def add_var_dec(arg)
+ add DepMask.new(arg)
+ end
+ def plan_pre_swig(plan)
+ plan.implicit = ImplicitName.new(@name,plan.implicit)
+ @members.each do |member|
+ if(member.respond_to?(:plan_pre_swig))
+ member.plan_pre_swig(plan)
+ else
+ MemberElementPreSWIG.check(plan,member)
+ end
+ end
+ end
+ def plan_post_swig(plan)
+ @members.each do |member|
+ if(member.respond_to?(:plan_post_swig))
+ member.plan_post_swig(plan)
+ else
+ MemberElementPostSWIG.check(plan,member)
+ end
+ end
+ end
+ def plan_cc(plan)
+ plan.implicit = ImplicitName.new(@name,plan.implicit)
+ @members.each do |member|
+ if(member.respond_to?(:plan_cc))
+ member.plan_cc(plan)
+ else
+ MemberElementCC.check(plan,member)
+ end
+ end
+ plan.implicit = plan.implicit.parent
+ end
+ def plan_header(plan)
+ plan.implicit = ImplicitName.new(@name,plan.implicit)
+ @members.each do |member|
+ if(member.respond_to?(:plan_header))
+ member.plan_header(plan)
+ else
+ MemberElementHeader.check(plan,member)
+ end
+ end
+ plan.implicit = plan.implicit.parent
+ end
+ def add val
+ @members << val
+ val
+ end
+ end
+ def initialize(rel_path)
+ @rel_path = rel_path
+ @cc_includes = []
+ @swig_includes_h = []
+ @swig_includes_swig = []
+ @header_includes = []
+ @spaces = []
+ @cc_usings = []
+ @cache = {}
+ end
+ def add_swig_body_include(inc_path)
+ @swig_includes_swig << CPP::SwigInclude.new(inc_path)
+ end
+ def add_swig_header_include(inc_path)
+ @swig_includes_h << CPP::Include.new(inc_path)
+ end
+ def add_swig_include(inc_path)
+ @swig_includes_h << CPP::Include.new(inc_path)
+ @swig_includes_swig << CPP::SwigInclude.new(inc_path)
+ end
+ def add_cc_include(inc_path)
+ @cc_includes << CPP::Include.new(inc_path)
+ end
+ def add_cc_using(using)
+ @cc_usings << CPP::Using.new(using)
+ end
+ def add_header_include(inc_path)
+ @header_includes << CPP::Include.new(inc_path)
+ end
+ def add_namespace(name,parent)
+ space = NameSpace.new(name,parent)
+ if(parent != self)
+ parent.add(space)
+ else
+ @spaces.push(space)
+ end
+ return space
+ end
+ def set(type,cached)
+ @cache[type] = cached
+ end
+ def get(type)
+ cached = @cache[type]
+ return cached if cached
+ cached = type.create(self)
+ cached_check = @cache[type]
+ return cached_check if cached_check
+ set(type,cached)
+ return cached
+ end
+ def write_cc_file(cpp_base,cc_file)
+ plan_cc = GroupPlan.new(nil,elems_cc = [])
+ @spaces.each do |space|
+ space.plan_cc(plan_cc)
+ end
+ suite = CPP::Suite.new(@cc_includes + @cc_usings + [plan_cc])
+ CPP.pretty_print(suite,cc_file)
+ end
+ def write_header_file(cpp_base,header_file)
+ plan_header = GroupPlan.new(nil,elems_cc = [])
+ @spaces.each do |space|
+ space.plan_header(plan_header)
+ end
+ suite = CPP::Suite.new(@header_includes + [plan_header])
+ include_guard = CPP::IncludeGuard.new(suite)
+ include_guard.name = @rel_path.upcase.gsub(/[\.\/\\]/,"_") + "_H_"
+ CPP.pretty_print(include_guard,header_file)
+ end
+ def write_swig_file(cpp_base,swig_file,q_filename)
+ plan_pre_swig = GroupPlan.new(nil, elems_cc = [])
+ plan_post_swig = GroupPlan.new(nil, elems_cc = [])
+ q_filename_underscore = q_filename.gsub(".","_")
+ @spaces.each do |space|
+ space.plan_pre_swig(plan_pre_swig)
+ space.plan_post_swig(plan_post_swig)
+ end
+ header_includes = CPP::SWIGBraces.new(CPP::Suite.new(@swig_includes_h))
+ # TODO(aschuh): I should probably %import any other headers from this queue's dependencies.
+ suite = CPP::Suite.new(["%module \"#{q_filename_underscore}\"",
+ "%typemap(javaimports) SWIGTYPE, SWIGTYPE * \"import aos.QueueGroup; import aos.Message; import aos.Time;\"",
+ "%pragma(java) jniclassimports=\"import aos.QueueGroup; import aos.Message; import aos.Time;\"",
+ "%pragma(java) moduleimports=\"import aos.QueueGroup; import aos.Message; import aos.Time;\"",
+ "%include \"std_string.i\"",
+ "%include \"stdint.i\""] +
+ [header_includes] +
+ #["%import \"aos/common/time.h\"",
+ #"%import \"aos/common/queue.h\""] +
+ ["%import \"aos/aos.swig\""] +
+ [plan_pre_swig] +
+ @swig_includes_swig +
+ [plan_post_swig]
+ )
+ CPP.pretty_print(suite, swig_file)
+ end
+end
diff --git a/aos/build/queues/cpp_pretty_print/file_pair_types.rb b/aos/build/queues/cpp_pretty_print/file_pair_types.rb
new file mode 100644
index 0000000..8f60b77
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/file_pair_types.rb
@@ -0,0 +1,204 @@
+module CPP
+end
+class CPP::TypePair
+ attr_accessor :name,:static,:dec
+ def initialize(namespace,name)
+ @space,@name = namespace,name
+ @members = []
+ @protections = {}
+ @dont_sort = {}
+ end
+ ProtectionTable = { :public => 0,:protected => 1,:private => 2 }
+ def comp(m1,m2)
+ if(!(@dont_sort[m1] || @dont_sort[m2]))
+ if(@protections[m1] && @protections[m2])
+ comp = ProtectionTable[@protections[m1]] <=> ProtectionTable[@protections[m2]]
+ return comp if(comp != 0)
+ end
+ comp = TypeTable[m1.class] <=> TypeTable[m2.class]
+ return comp if(comp != 0)
+ end
+ return @stable[m1] <=> @stable[m2]
+ end
+ def set_parent(parent)
+ @parent = parent
+ end
+ def add_class(name)
+ return add_member(:public,CPP::ClassPair.new(self,name))
+ end
+ def add_struct(name)
+ return add_member(:public,CPP::StructPair.new(self,name))
+ end
+ def add_cc_comment(*strs)
+ strs.each do |str|
+ @members << comment = CPP::CCMemberWrapper.new(CPP::Comment.new(str))
+ @protections[comment] = @protection
+ end
+ #@dont_sort[comment] = true
+ end
+ def method_prefix()
+ @space.method_prefix + "#@name::"
+ end
+ def chop_method_prefix()
+ @space.chop_method_prefix + "#@name::"
+ end
+ def pp(state)
+ @stable = {}
+ @members.each_with_index { |mem,i| @stable[mem] = i }
+ members = @members.sort { |m1,m2| comp(m1,m2) }
+
+ state.needs_semi = false
+ state.v_pad(2)
+ if(@static)
+ state.print("static ")
+ end
+ if(@parent)
+ state.print("#{self.class.type_name} #{@name} : #{@parent} {\n")
+ else
+ state.print("#{self.class.type_name} #{@name} {\n")
+ end
+ state.indent += 2
+ protection = nil
+ members.each do |member|
+ if(protection != @protections[member])
+ state.indent -= 1
+ state.needs_semi = false
+ state.v_pad(2) if(protection)
+ protection = @protections[member]
+ state.print("#{protection}:\n")
+ state.indent += 1
+ state.endline()
+ end
+ state.endline()
+ state.needs_semi = true
+ if(member.respond_to?(:pp_header_file))
+ member.pp_header_file(state)
+ else
+ state.pp(member)
+ end
+ state.endline()
+ end
+ state.indent -= 2
+ state.needs_semi = true
+ if(@dec)
+ state.print("\n} #{@dec}")
+ else
+ state.print("\n}")
+ end
+ state.v_pad(2)
+ end
+ def pp_header_file(state)
+ pp(state)
+ end
+ def pp_cc_file(state)
+ @members.each do |member|
+ state.needs_semi = true
+ member.pp_cc_file(state) if(member.respond_to?(:pp_cc_file))
+ state.endline()
+ end
+ end
+ def def_func(*args)
+ func = CPP::MemberFunc.new(self,*args)
+ @protections[func] = @protection
+ @members << func
+ return func
+ end
+end
+class CPP::CCMemberWrapper
+ def initialize(member)
+ @member = member
+ end
+ def pp_header_file(state) ; end
+ def pp_cc_file(state)
+ state.pp(@member)
+ end
+end
+class CPP::ClassPair < CPP::TypePair
+ attr_accessor :name
+ def initialize(namespace,name)
+ super(namespace,name)
+ @protection = :public #default to public
+ end
+ def add_member(protection,member)
+ @protection = protection
+ @members << member
+ @protections[member] = protection
+ return member
+ end
+ def public() ; @protection = :public ; end
+ def protected() ; @protection = :protected ; end
+ def private() ; @protection = :private ; end
+ def self.type_name() ; "class" ; end
+end
+class CPP::StructPair < CPP::TypePair
+ def self.type_name() ; "struct" ; end
+ def add_member(member)
+ @members << member
+ return member
+ end
+end
+CPP::TypePair::TypeTable = { CPP::StructPair => 0, CPP::ClassPair => 1,CPP::Constructor => 2 }
+CPP::TypePair::TypeTable.default = 3
+class CPP::TemplateClass < CPP::ClassPair
+ def initialize(namespace,name)
+ super(namespace,name)
+ @t_args = CPP::Args.new()
+ end
+ def spec_args()
+ return @spec_args ||= CPP::Args.new()
+ end
+ def pp(state)
+ @stable = {}
+ @members.each_with_index { |mem,i| @stable[mem] = i }
+ members = @members.sort { |m1,m2| comp(m1,m2) }
+ state.needs_semi = false
+ state.v_pad(2)
+ if(@t_args.length > 0)
+ state.pp("template < ")
+ state.pp(@t_args)
+ else
+ state.pp("template <")
+ end
+ state.pp(">\n")
+ state.pp("class #@name")
+ if(@spec_args)
+ state.pp("< ")
+ state.pp(@spec_args)
+ state.pp("> {")
+ else
+ state.pp(" {")
+ end
+ state.endline()
+ state.indent += 2
+ protection = nil
+ members.each do |member|
+ if(protection != @protections[member])
+ state.indent -= 1
+ state.needs_semi = false
+ state.v_pad(2) if(protection)
+ protection = @protections[member]
+ state.print("#{protection}:\n")
+ state.indent += 1
+ state.endline()
+ end
+ state.endline()
+ state.needs_semi = true
+ if(member.respond_to?(:pp_inline))
+ member.pp_inline(state)
+ else
+ state.pp(member)
+ end
+ state.endline()
+ end
+ state.indent -= 2
+ state.needs_semi = true
+ if(@dec)
+ state.print("\n} #{@dec}")
+ else
+ state.print("\n}")
+ end
+ state.v_pad(2)
+ end
+ def pp_cc_file(state); end
+end
+
diff --git a/aos/build/queues/cpp_pretty_print/standard_types.rb b/aos/build/queues/cpp_pretty_print/standard_types.rb
new file mode 100644
index 0000000..566f542
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/standard_types.rb
@@ -0,0 +1,363 @@
+module CPP
+ class Class
+
+ end
+ class Funct
+ attr_accessor :retval,:name,:args,:suite
+ def initialize(retval = nil,name = nil,args = Args.new(),suite = Suite.new())
+ @retval,@name,@args,@suite = retval,name,args,suite
+ end
+ def pp(state)
+ state.pp(@retval)
+ state.print(" ")
+ state.pp(@name)
+ state.print("(")
+ state.pp(@args)
+ state.print(")")
+ state.pp(@suite)
+ end
+ end
+ class If
+ attr_accessor :cond,:suite,:else_suite
+ def initialize(cond = nil,suite = Suite.new(),else_suite = nil)
+ @cond,@suite,@else_suite = cond,suite,else_suite
+ end
+ def pp(state)
+ state.print("if (")
+ state.pp(@cond)
+ state.print(") ")
+ state.needs_semi = false
+ state.pp(@suite)
+ if(@else_suite)
+ state.print(" else ")
+ state.pp(@else_suite)
+ end
+ end
+ def else_suite()
+ return(@else_suite ||= Suite.new())
+ end
+ end
+ class For
+ attr_accessor :init,:cond,:update,:suite
+ def initialize(init = nil,cond = nil,update = nil,suite = Suite.new())
+ @init,@cond,@update,@suite = init,cond,update,suite
+ end
+ def pp(state)
+ state.print("for (")
+ Args.new([@init,@cond,@update]).pp(state,";")
+ state.print(") ")
+ state.needs_semi = false
+ state.pp(@suite)
+ end
+ end
+ class Args < Array
+ attr_accessor :dont_wrap
+ def pp(state,sep = ",")
+ pos = start = state.col
+ self.each_with_index do |arg,i|
+ #puts "#{state.col - start} , #{start}"
+ state.print(sep) if(i != 0)
+ if(pos > 80)
+ state.wrap(state.indent + 4)
+ pos = start = state.col
+ elsif(state.col * 2 - pos > 80 && !@dont_wrap)
+ state.wrap(start)
+ start = pos
+ else
+ state.print(" ") if(i != 0)
+ pos = state.col
+ end
+ state.pp(arg)
+ end
+ end
+ end
+ class Suite < Array
+ def pp(state)
+ state.print("{")
+ state.>>
+ state.needs_semi = false
+ self.pp_no_braces(state)
+ state.<<
+ state.print("}")
+ end
+ def pp_no_braces(state)
+ self.each do |arg,i|
+ state.endline()
+ state.needs_semi = true
+ state.pp(arg)
+ state.endline()
+ end
+ end
+ def pp_one_line(state)
+ if(self.length == 1)
+ state.needs_semi = true
+ state.print("{ ")
+ state.pp(self[0])
+ state.print(";") if(state.needs_semi)
+ state.needs_semi = false
+ state.print(" }")
+ else
+ self.pp(state)
+ end
+ end
+ end
+ class FuncCall
+ attr_accessor :name,:args
+ def initialize(name = nil,args = Args.new())
+ @name,@args = name,args
+ end
+ def self.build(name,*args)
+ self.new(name,Args.new(args))
+ end
+ def pp(state)
+ state.pp(@name)
+ state.print("(")
+ state.pp(@args)
+ state.print(")")
+ end
+ end
+ class BIT_OR
+ attr_accessor :val1,:val2
+ def initialize(val1,val2)
+ @val1,@val2 = val1,val2
+ end
+ def pp(state)
+ state.pp(@val1)
+ state.print(" | ")
+ state.pp(@val2)
+ end
+ end
+ class LT
+ attr_accessor :val1,:val2
+ def initialize(val1,val2)
+ @val1,@val2 = val1,val2
+ end
+ def pp(state)
+ state.pp(@val1)
+ state.print(" < ")
+ state.pp(@val2)
+ end
+ end
+ class Div
+ attr_accessor :val1,:val2
+ def initialize(val1,val2)
+ @val1,@val2 = val1,val2
+ end
+ def pp(state)
+ state.pp(@val1)
+ state.print(" / ")
+ state.pp(@val2)
+ end
+ end
+ class Add
+ attr_accessor :val1,:val2
+ def initialize(val1,val2)
+ @val1,@val2 = val1,val2
+ end
+ def pp(state)
+ state.pp(@val1)
+ state.print(" + ")
+ state.pp(@val2)
+ end
+ end
+ class Member
+ attr_accessor :obj,:name
+ def initialize(obj,name)
+ @obj,@name = obj,name
+ end
+ def pp(state)
+ state.pp(@obj)
+ state.print(".")
+ state.pp(@name)
+ end
+ end
+ class PointerMember
+ attr_accessor :obj,:name
+ def initialize(obj,name)
+ @obj,@name = obj,name
+ end
+ def pp(state)
+ state.pp(@obj)
+ state.print("->")
+ state.pp(@name)
+ end
+ end
+ class Minus
+ attr_accessor :val
+ def initialize(val)
+ @val = val
+ end
+ def pp(state)
+ state.print("-")
+ state.pp(@val)
+ end
+ end
+ class Not
+ attr_accessor :val
+ def initialize(val)
+ @val = val
+ end
+ def pp(state)
+ state.print("!")
+ state.pp(@val)
+ end
+ end
+ class Address
+ attr_accessor :val
+ def initialize(val)
+ @val = val
+ end
+ def pp(state)
+ state.print("&")
+ state.pp(@val)
+ end
+ end
+ class Paran
+ attr_accessor :val
+ def initialize(val)
+ @val = val
+ end
+ def pp(state)
+ state.print("(")
+ state.pp(@val)
+ state.print(")")
+ end
+ end
+ class Assign
+ attr_accessor :lval,:rval
+ def initialize(lval = nil,rval = Args.new())
+ @lval,@rval = lval,rval
+ end
+ def pp(state)
+ state.pp(@lval)
+ state.print(" = ")
+ state.pp(@rval)
+ end
+ end
+ class PointerDeref
+ attr_accessor :val
+ def initialize(val)
+ @val = val
+ end
+ def pp(state)
+ state.print("*")
+ state.pp(@val)
+ end
+ end
+ class Cast
+ attr_accessor :to,:val
+ def initialize(to,val)
+ @to,@val = to,val
+ end
+ def pp(state)
+ state.print("(")
+ state.pp(@to)
+ state.print(")")
+ state.pp(@val)
+ end
+ end
+ class VarDec
+ attr_accessor :type,:name
+ def initialize(type = nil,name = nil)
+ @type,@name = type,name
+ end
+ def pp(state)
+ state.pp(@type)
+ state.print(" ")
+ state.pp(@name)
+ end
+ end
+ class Return
+ attr_accessor :val
+ def initialize(val = nil)
+ @val = val
+ end
+ def pp(state)
+ state.print("return ")
+ state.pp(@val)
+ end
+ end
+ class TraversalState
+ attr_accessor :needs_semi,:indent,:col
+ def initialize(file)
+ @file = file
+ @indent = 0
+ @not_indented = true
+ @just_endlined = true
+ @hold_points = []
+ @col = 0
+ end
+ def set_hold_point()
+ @hold_points.push(@col)
+ end
+ def wrap(col)
+ @file.print("\n")
+ @file.print(" " * col)
+ @col = col
+ end
+ def suppress_indent()
+ @not_indented = false
+ end
+ def <<()
+ @indent -= 2
+ end
+ def >>()
+ @indent += 2
+ end
+ def pp(ast)
+ return ast.pp(self) if(ast.respond_to?(:pp))
+ self.print(ast)
+ end
+ def print(chars)
+ return print_no_split(chars) if(!chars.respond_to?(:split))
+ chars.split(/\n/,-1).each_with_index do |line,i|
+ endline() if(i != 0)
+ print_no_split(line) if(line && line.length > 0)
+ end
+ end
+ def print_no_split(chars)
+ if(@not_indented)
+ @file.print(" "*@indent)
+ @col += @indent
+ @not_indented = false
+ end
+ if(chars)
+ chars = chars.to_s
+ if(chars.length > 0)
+ @col += chars.length
+ @file.print(chars)
+ @just_endlined = false
+ @v_pad = 0
+ end
+ end
+ end
+ def endline()
+ return if(@just_endlined)
+ @file.print(";") if(@needs_semi)
+ @needs_semi = false
+ @file.print("\n")
+ @not_indented = true
+ @just_endlined = true
+ @hold_points.clear()
+ @v_pad += 1
+ @col = 0
+ end
+ def v_pad(n)
+ while(@v_pad < n)
+ force_endline()
+ end
+ end
+ def force_endline()
+ @just_endlined = false
+ endline()
+ end
+ end
+ def self.pretty_print(ast,file)
+ state = TraversalState.new(file)
+ if(ast.respond_to?(:pp_no_braces))
+ ast.pp_no_braces(state)
+ else
+ state.pp(ast)
+ end
+ end
+end
diff --git a/aos/build/queues/cpp_pretty_print/swig.rb b/aos/build/queues/cpp_pretty_print/swig.rb
new file mode 100644
index 0000000..ac6d062
--- /dev/null
+++ b/aos/build/queues/cpp_pretty_print/swig.rb
@@ -0,0 +1,60 @@
+class CPP::SwigPragma
+ attr_accessor :suite
+ def initialize(language, pragmatype, suite = CPP::Suite.new())
+ @suite = suite
+ @language = language
+ @pragmatype = pragmatype
+ end
+ def pp(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("%pragma(#{@language}) #{@pragmatype}=%{")
+ state.endline()
+ if(@suite.respond_to?(:pp_no_braces))
+ @suite.pp_no_braces(state)
+ else
+ state.pp(@suite)
+ end
+ state.endline()
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("%}")
+ state.endline()
+ state.endline()
+ end
+end
+class CPP::SWIGBraces
+ attr_accessor :suite
+ def initialize(suite = CPP::Suite.new())
+ @suite = suite
+ end
+ def pp(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("%{")
+ state.endline()
+ if(@suite.respond_to?(:pp_no_braces))
+ @suite.pp_no_braces(state)
+ else
+ state.pp(@suite)
+ end
+ state.endline()
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("%}")
+ state.endline()
+ state.endline()
+ end
+end
+class CPP::SwigInclude
+ attr_accessor :filename
+ def initialize(filename)
+ @filename = filename
+ end
+ def pp(state)
+ state.needs_semi = false
+ state.suppress_indent()
+ state.print("%include #{@filename}")
+ state.endline()
+ end
+end
diff --git a/aos/build/queues/objects/errors.rb b/aos/build/queues/objects/errors.rb
new file mode 100644
index 0000000..d776a22
--- /dev/null
+++ b/aos/build/queues/objects/errors.rb
@@ -0,0 +1,43 @@
+class QError < Exception
+ def initialize(msg)
+ super()
+ @msg = msg
+ @qstacktrace = []
+ end
+ def self.set_name(name)
+ @pretty_name = name
+ end
+ def self.pretty_name()
+ @pretty_name
+ end
+ def to_s
+ msg = "Error:(#{self.class.pretty_name})\n\t"
+ msg += @msg
+ msg += "\n" if(msg[-1] != "\n")
+ @qstacktrace.each do |part|
+ part = part.q_stack_name if(part.respond_to?(:q_stack_name))
+ msg += "\tfrom: #{part}\n"
+ end
+ return msg
+ end
+ set_name("Base Level Exception.")
+ attr_accessor :qstacktrace
+end
+class QSyntaxError < QError
+ def initialize(msg)
+ super(msg)
+ end
+ set_name("Syntax Error")
+end
+class QNamespaceCollision < QError
+ def initialize(msg)
+ super(msg)
+ end
+ set_name("Namespace Collision")
+end
+class QImportNotFoundError < QError
+ def initialize(msg)
+ super(msg)
+ end
+ set_name("Couldn't Find Target of Import Statement")
+end
diff --git a/aos/build/queues/objects/interface.rb b/aos/build/queues/objects/interface.rb
new file mode 100644
index 0000000..52332b6
--- /dev/null
+++ b/aos/build/queues/objects/interface.rb
@@ -0,0 +1,69 @@
+class MessageElementReq
+ def initialize(type,name)
+ @type = type
+ @name = name
+ end
+ def self.parse(tokens)
+ type = tokens.expect(:tWord).data
+ name = tokens.expect(:tWord).data
+ tokens.expect(:tSemi)
+ return self.new(type,name)
+ end
+end
+class QueueReq
+ def initialize(name,type = nil)
+ @name = name
+ @type = type
+ end
+ def self.parse(tokens)
+ type_or_name = tokens.expect(:tWord).data
+ if(tokens.peak == :tSemi)
+ tokens.expect(:tSemi)
+ return self.new(type_or_name)
+ else
+ name = tokens.expect(:tWord).data
+ tokens.expect(:tSemi)
+ return self.new(name,type_or_name)
+ end
+ end
+end
+class InterfaceStmt < QStmt
+ def initialize(name,elements)
+ @name = name
+ @elements = elements
+ end
+ def q_eval(locals)
+
+ end
+ def self.check_type(tokens,new_type,old_type)
+ return new_type if(old_type == nil)
+ if(new_type != old_type)
+ tokens.qError(<<ERROR_MSG)
+error: intermixing queue definitions (a queue_group feature)
+ and type definitions (a message_group feature)
+ this results in an undefined type value.
+ Wot. Wot.
+ERROR_MSG
+ end
+ return old_type
+ end
+ def self.parse(tokens)
+ name = tokens.expect(:tWord).data
+ values = []
+ type = nil
+ tokens.expect(:tOpenB)
+ while(tokens.peak != :tCloseB)
+ if(tokens.peak.data == "queue")
+ tokens.expect(:tWord)
+ values << QueueReq.parse(tokens)
+ type = check_type(tokens,:queue_group,type)
+ else
+ values << MessageElementReq.parse(tokens)
+ type = check_type(tokens,:message_group,type)
+ end
+ end
+ tokens.expect(:tCloseB)
+ tokens.expect(:tSemi)
+ self.new(name,values)
+ end
+end
diff --git a/aos/build/queues/objects/namespaces.rb b/aos/build/queues/objects/namespaces.rb
new file mode 100644
index 0000000..b799d36
--- /dev/null
+++ b/aos/build/queues/objects/namespaces.rb
@@ -0,0 +1,210 @@
+class LocalSituation
+ attr_accessor :globals,:local
+ def initialize(globals)
+ @globals = globals
+ @local = nil
+ end
+ def package=(qualified)
+ if(@local)
+ raise QSyntaxError.new(<<ERROR_MSG)
+You are redefining the package path.
+ Stuff might break if you do that.
+ Other options include: using another header file, and just using the same namespace.
+ If you are confident that you need this you can remove this check at
+ #{__FILE__}:#{__LINE__}.
+ Or file a feature request.
+ But that would be weird...
+ Wot. Wot.
+ERROR_MSG
+ end
+ @local = @globals.space
+ qualified.names.each do |name|
+ @local = @local.get_make(name)
+ end
+ end
+ def register(value)
+ if(!@local)
+ raise QError.new(<<ERROR_MSG)
+There is no package path defined, This is a big problem because
+ we are kindof expecting you to have a package path...
+ use a :
+ package my_super.cool.project;
+ statement to remedy this situation. (or file a feature request)
+ Wot. Wot.
+ERROR_MSG
+ end
+ @local[value.name] = value
+ value.parent = @local if(value.respond_to?(:parent=))
+ value.loc = @local
+ end
+ def bind(bind_to)
+ return BoundSituation.new(self,bind_to)
+ end
+end
+class BoundSituation < LocalSituation
+ def initialize(locals,bind_to)
+ @globals = globals
+ @local = bind_to
+ end
+end
+class NameSpace
+ attr_accessor :parent,:name
+ def initialize(name = nil,parent = nil)
+ @name = name
+ @parent = parent
+ @spaces = {}
+ end
+ def []=(key,val)
+ if(old_val = @spaces[key])
+ old_val = old_val.created_by if(old_val.respond_to?(:created_by) && old_val.created_by)
+ if(old_val.respond_to?(:q_stack_name))
+ old_val = old_val.q_stack_name
+ else
+ old_val = "eh, it is a #{old_val.class} thats all I know..."
+ end
+ raise QNamespaceCollision.new(<<ERROR_MSG)
+Woah! The name #{queue_name(key).inspect} is already taken by some chap at #{old_val}.
+\tFind somewhere else to peddle your wares.
+\tWot. Wot.
+ERROR_MSG
+ end
+ @spaces[key] = val
+ end
+ def to_cpp_id(name)
+ txt = @name + "::" + name
+ return @parent.to_cpp_id(txt) if(@parent && parent.name)
+ return "::" + txt
+ end
+ def queue_name(queue)
+ get_name() + "." + queue
+ end
+ def [](key)
+ #puts "getting #{get_name}.#{key}"
+ @spaces[key]
+ end
+ def get_make(name)
+ @spaces[name] ||= self.class.new(name,self)
+ end
+ def get_name()
+ if(@parent)
+ return "#{@parent.get_name}.#{@name}"
+ else
+ return "#{@name}"
+ end
+ end
+ def create(cpp_tree)
+ if(@parent && @parent.name)
+ parent = cpp_tree.get(@parent)
+ else
+ parent = cpp_tree
+ end
+ return cpp_tree.add_namespace(@name,parent)
+ end
+ def to_s()
+ "<NameSpace: #{get_name()}>"
+ end
+ def inspect()
+ "<NameSpace: #{get_name()}>"
+ end
+ def root()
+ return self if(@parent == nil)
+ return @parent.root
+ end
+end
+class Globals
+ attr_accessor :space
+ def initialize()
+ @space = NameSpace.new()
+ @space.get_make("aos")
+ @include_paths = []
+ end
+ def paths()
+ @include_paths
+ end
+ def add_path(path)
+ @include_paths << path
+ end
+ def find_file(filename)
+ @include_paths.each do |path_name|
+ new_path = File.expand_path(path_name) + "/" + filename
+ if(File.exists?(new_path))
+ return new_path
+ end
+ end
+ raise QImportNotFoundError.new(<<ERROR_MSG)
+Problem Loading:#{filename.inspect} I looked in:
+\t#{(@include_paths.collect {|name| name.inspect}).join("\n\t")}
+\tbut alas, it was nowhere to be found.
+\tIt is popular to include the top of the repository as the include path start,
+\tand then reference off of that.
+\tI would suggest doing that and then trying to build again.
+\tWot. Wot.
+ERROR_MSG
+ end
+end
+class QualifiedName
+ attr_accessor :names,:off_root
+ def initialize(names,off_root = false)
+ @names = names
+ @off_root = off_root
+ end
+ def test_lookup(namespace)
+ @names.each do |name|
+ namespace = namespace[name]
+ return nil if(!namespace)
+ end
+ return namespace
+ end
+ def is_simple?()
+ return !@off_root && @names.length == 1
+ end
+ def to_simple()
+ return @names[-1]
+ end
+ def to_s()
+ if(@off_root)
+ return ".#{@names.join(".")}"
+ else
+ return @names.join(".")
+ end
+ end
+ def lookup(locals)
+ if(@off_root)
+ local = locals.globals.space
+ else
+ local = locals.local
+ end
+ target = nil
+ while(!target && local)
+ target = test_lookup(local)
+ local = local.parent
+ end
+ return target if(target)
+ if(@off_root)
+ raise QError.new(<<ERROR_MSG)
+I was looking for .#{@names.join(".")}, but alas, it was not under
+\tthe root namespace.
+\tI'm really sorry old chap.
+\tWot. Wot.
+ERROR_MSG
+ else
+ raise QError.new(<<ERROR_MSG)
+I was looking for #{@names.join(".")}, but alas, I could not find
+\tit in #{locals.local.get_name} or any parent namespaces.
+\tI'm really sorry old chap.
+\tWot. Wot.
+ERROR_MSG
+ end
+ end
+ def self.parse(tokens)
+ names = []
+ off_root = (tokens.peak == :tDot)
+ tokens.next if(off_root)
+ names << tokens.expect(:tWord).data
+ while(tokens.peak == :tDot)
+ tokens.next
+ names << tokens.expect(:tWord).data
+ end
+ return self.new(names,off_root)
+ end
+end
diff --git a/aos/build/queues/objects/q_file.rb b/aos/build/queues/objects/q_file.rb
new file mode 100644
index 0000000..f683dda
--- /dev/null
+++ b/aos/build/queues/objects/q_file.rb
@@ -0,0 +1,148 @@
+class QStmt
+ def set_line(val)
+ @file_line = val
+ return self
+ end
+ def q_stack_name()
+ @file_line
+ end
+ def self.method_added(name)
+ @wrapped ||= {}
+ return if(name != :q_eval && name != :q_eval_extern)
+ return if(@wrapped[name])
+ @wrapped[name] = true
+ method = self.instance_method(name)
+ define_method(name) do |*args,&blk|
+ begin
+ method.bind(self).call(*args,&blk)
+ rescue QError => e
+ e.qstacktrace << self
+ raise e
+ end
+ end
+ end
+
+end
+class ImportStmt < QStmt
+ def initialize(filename)
+ @filename = filename
+ end
+ def q_eval(locals)
+ filename = locals.globals.find_file(@filename)
+ #puts "importing #{filename.inspect}"
+ q_file = QFile.parse(filename)
+ q_output = q_file.q_eval_extern(locals.globals)
+ q_output.extern = true
+ return Target::QInclude.new(@filename + ".h")
+ end
+ def self.parse(tokens)
+ line = tokens.pos
+ to_import = (tokens.expect(:tString) do |token|
+ <<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a "filename" for this import statement.
+\tSomething like: import "super_cool_file";
+\tWot.Wot
+ERROR_MSG
+ end).data
+ tokens.expect(:tSemi) do |token|
+ <<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a ";" to finish off this import statement
+\tat line #{line};
+\tSomething like: import #{to_import.inspect};
+\tWot.Wot #{" "*to_import.inspect.length}^
+ERROR_MSG
+ end
+ return self.new(to_import).set_line(line)
+ end
+end
+class PackageStmt < QStmt
+ def initialize(name)
+ @name = name
+ end
+ def q_eval(locals)
+ locals.package = @name
+ return nil
+ end
+ def self.parse(tokens)
+ line = tokens.pos
+ qualified_name = QualifiedName.parse(tokens)
+ tokens.expect(:tSemi)
+ return self.new(qualified_name).set_line(line)
+ end
+end
+class QFile
+ attr_accessor :namespace
+ def initialize(filename,suite)
+ @filename,@suite = filename,suite
+ end
+ def q_eval(globals = Globals.new())
+ local_pos = LocalSituation.new(globals)
+ q_file = Target::QFile.new()
+ @suite.each do |name|
+ val = name.q_eval(local_pos)
+ if(val)
+ if(val.respond_to?(:create))
+ q_file.add_type(val)
+ end
+ end
+ end
+ @namespace = local_pos.local
+ return q_file
+ end
+ def q_eval_extern(globals)
+ local_pos = LocalSituation.new(globals)
+ q_file = Target::QFile.new()
+ @suite.each do |name|
+ if(name.respond_to?(:q_eval_extern))
+ val = name.q_eval_extern(local_pos)
+ else
+ val = name.q_eval(local_pos)
+ end
+ if(val)
+ if(val.respond_to?(:create))
+ q_file.add_type(val)
+ end
+ end
+ end
+ return q_file
+ end
+ def self.parse(filename)
+ tokens = Tokenizer.new(filename)
+ suite = []
+ while(tokens.peak != :tEnd)
+ token = tokens.expect(:tWord) do |token| #symbol
+ <<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}.
+\tI was really looking for a "package", "import", "queue_group",
+\t"message", or "queue" statement to get things moving.
+\tSomething like: import "super_cool_file";
+\tWot.Wot
+ERROR_MSG
+ end
+ case token.data
+ when "package"
+ suite << PackageStmt.parse(tokens)
+ when "import"
+ suite << ImportStmt.parse(tokens)
+ when "queue_group"
+ suite << QueueGroupStmt.parse(tokens)
+ when "message"
+ suite << MessageStmt.parse(tokens)
+ when "queue"
+ suite << QueueStmt.parse(tokens)
+ when "interface"
+ suite << InterfaceStmt.parse(tokens)
+ else
+ tokens.qError(<<ERROR_MSG)
+expected a "package","import","queue","queue_group", or "message" statement rather
+ than a #{token.data.inspect}, (whatever that is?)
+ oh! no! a feature request!?
+ Wot. Wot.
+ERROR_MSG
+ end
+ end
+ return self.new(filename,suite)
+ end
+end
diff --git a/aos/build/queues/objects/queue.rb b/aos/build/queues/objects/queue.rb
new file mode 100644
index 0000000..5693486
--- /dev/null
+++ b/aos/build/queues/objects/queue.rb
@@ -0,0 +1,154 @@
+class MessageElementStmt < QStmt
+ attr_accessor :name
+ def initialize(type,name,length = nil) #lengths are for arrays
+ @type = type
+ @name = name
+ @length = length
+ end
+ CommonMistakes = {"short" => "int16_t","int" => "int32_t","long" => "int64_t"}
+ def check_type_error()
+ if(!(Sizes[@type] || (@length != nil && @type == "char")) )
+ if(correction = CommonMistakes[@type])
+ raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tplease use #{correction} instead. Your type is not supported because we
+\twant to guarantee that the sizes of the messages stay the same across platforms.
+\tWot. Wot.
+ERROR_MSG
+ elsif(@type == "char")
+ raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tyou need your declaration to be a char array like: char[10].
+\tor, please use int8_t or uint8_t.
+\tWot. Wot.
+ERROR_MSG
+ else
+ raise QError.new(<<ERROR_MSG)
+Hey! you have a \"#{@type}\" in your message statement.
+\tThat is not in the list of supported types.
+\there is the list of supported types:
+\tint{8,16,32,64}_t,uint{8,16,32,64}_t,bool,float,double#{len_comment}
+\tWot. Wot.
+ERROR_MSG
+ end
+ end
+ end
+
+ PrintFormat = {"bool" => "%c",
+ "float" => "%f",
+ "char" => "%c",
+ "double" => "%f",
+ "uint8_t" => "%\"PRIu8\"",
+ "uint16_t" => "%\"PRIu16\"",
+ "uint32_t" => "%\"PRIu32\"",
+ "uint64_t" => "%\"PRIu64\"",
+ "int8_t" => "%\"PRId8\"",
+ "int16_t" => "%\"PRId16\"",
+ "int32_t" => "%\"PRId32\"",
+ "int64_t" => "%\"PRId64\""}
+ def toPrintFormat()
+ if(format = PrintFormat[@type])
+ return format;
+ end
+ raise QError.new(<<ERROR_MSG)
+Somehow this slipped past me, but
+\tI couldn't find the print format of #{@type}. Really, my bad.
+\tWot. Wot.
+ERROR_MSG
+ end
+
+ Sizes = {"bool" => 1, "float" => 4,"double" => 8}
+ [8,16,32,64].each do |len|
+ Sizes["int#{len}_t"] = len / 8
+ Sizes["uint#{len}_t"] = len / 8
+ end
+ Zero = {"float" => "0.0f","double" => "0.0","bool" => "false"}
+ def size()
+ if(size = Sizes[@type]); return size; end
+ return 1 if(@type == "char")
+ raise QError.new(<<ERROR_MSG)
+Somehow this slipped past me, but
+\tI couldn't find the size of #{@type}. Really, my bad.
+\tWot. Wot.
+ERROR_MSG
+ end
+ def q_eval(locals)
+ check_type_error()
+ if(@length == nil)
+ member = Target::MessageElement.new(@type,@name)
+ else
+ member = Target::MessageArrayElement.new(@type,@name,@length)
+ end
+ member.size = size()
+ member.zero = Zero[@type] || "0";
+ member.printformat = toPrintFormat()
+ locals.local.add_member(member)
+ end
+ def self.parse(tokens)
+ line = tokens.pos
+ type = tokens.expect(:tWord).data
+ len = nil
+ if(tokens.peak == :tOpenB)
+ tokens.expect(:tOpenB)
+ len = tokens.expect(:tNumber).data
+ tokens.expect(:tCloseB)
+ end
+ name = tokens.expect(:tWord).data
+ tokens.expect(:tSemi)
+ return self.new(type,name,len).set_line(line)
+ end
+end
+class MessageStmt < QStmt
+ def initialize(name,suite)
+ @name = name
+ @suite = suite
+ end
+ def q_eval(locals)
+ group = Target::MessageDec.new(@name)
+ locals.register(group)
+ @suite.each do |stmt|
+ stmt.q_eval(locals.bind(group))
+ end
+ return group
+ end
+ def self.parse(tokens)
+ name = tokens.expect(:tWord).data
+ values = []
+ tokens.expect(:tOpenB)
+ while(tokens.peak != :tCloseB)
+ values << MessageElementStmt.parse(tokens)
+ end
+ names = {}
+ values.each do |val|
+ if(names[val.name])
+ raise QSyntaxError.new(<<ERROR_MSG)
+Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
+\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
+\tWot. Wot.
+ERROR_MSG
+ end
+ names[val.name] = val
+ end
+ tokens.expect(:tCloseB)
+ tokens.expect(:tSemi)
+ self.new(name,values)
+ end
+end
+class QueueStmt < QStmt
+ def initialize(type,name)
+ @type,@name = type,name
+ end
+ def q_eval(locals)
+ queue = Target::QueueDec.new(@type.lookup(locals),@name)
+ locals.register(queue)
+ locals.local.add_queue(queue) if(locals.local.respond_to?(:add_queue))
+ return queue
+ end
+ def self.parse(tokens)
+ line = tokens.pos
+ type_name = QualifiedName.parse(tokens)
+ name = tokens.expect(:tWord).data
+ tokens.expect(:tSemi)
+ return self.new(type_name,name).set_line(line)
+ end
+end
diff --git a/aos/build/queues/objects/queue_group.rb b/aos/build/queues/objects/queue_group.rb
new file mode 100644
index 0000000..136834f
--- /dev/null
+++ b/aos/build/queues/objects/queue_group.rb
@@ -0,0 +1,115 @@
+class QueueGroupTypeStmt < QStmt
+ def initialize(name,suite)
+ @name,@suite = name,suite
+ end
+ def q_eval(locals)
+ group = Target::QueueGroupDec.new(@name)
+ group.created_by = self
+ locals.register(group)
+ @suite.each do |stmt|
+ stmt.q_eval(locals.bind(group))
+ end
+ return group
+ end
+end
+class ImplementsStmt < QStmt
+ def initialize(name)
+ @name = name
+ end
+ def q_eval(locals)
+
+ end
+ def self.parse(tokens)
+ name = QualifiedName.parse(tokens)
+ tokens.expect(:tSemi)
+ return self.new(name)
+ end
+end
+class QueueGroupStmt < QStmt
+ def initialize(type,name)
+ @type,@name = type,name
+ end
+ def q_eval(locals)
+ group = Target::QueueGroup.new(@type.lookup(locals),@name)
+ group.created_by = self
+ locals.register(group)
+ return group
+ end
+ def self.parse(tokens)
+ line = tokens.pos
+ type_name = QualifiedName.parse(tokens)
+ if(type_name.names.include?("queue_group"))
+ tokens.qError(<<ERROR_MSG)
+I was looking at the identifier you gave
+\tfor the queue group type between line #{line} and #{tokens.pos}
+\tThere shouldn't be a queue_group type called queue_group
+\tor including queue_group in it's path, it is a reserved keyword.
+\tWot. Wot.
+ERROR_MSG
+ end
+ if(tokens.peak == :tOpenB)
+ if(type_name.is_simple?())
+ type_name = type_name.to_simple
+ else
+ tokens.qError(<<ERROR_MSG)
+You gave the name: "#{type_name.to_s}" but you're only allowed to
+\thave simple names like "#{type_name.names[-1]}" in queue_group definitions
+\ttry something like:
+\tqueue_group ControlLoop { }
+\tWot. Wot.
+ERROR_MSG
+ end
+ tokens.expect(:tOpenB)
+ suite = []
+ while(tokens.peak != :tCloseB)
+ token = tokens.expect(:tWord) do |token|
+ <<ERROR_MSG
+I'm a little confused, I found a #{token.humanize} at #{token.pos}
+\tbut what I really wanted was an identifier signifying a nested
+\tmessage declaration, or queue definition, or an impliments statement.
+\tWot.Wot
+ERROR_MSG
+ end
+ case token.data
+ when "message"
+ suite << MessageStmt.parse(tokens)
+ when "queue"
+ suite << QueueStmt.parse(tokens)
+ when "implements"
+ suite << ImplementsStmt.parse(tokens)
+ else
+ tokens.qError(<<ERROR_MSG)
+expected a "queue","implements" or "message" statement rather
+\tthan a #{token.data.inspect}.
+\tWot. Wot.
+ERROR_MSG
+ end
+ end
+ tokens.expect(:tCloseB)
+ obj = QueueGroupTypeStmt.new(type_name,suite).set_line(line)
+ else
+ name = (tokens.expect(:tWord) do |token|
+ <<ERROR_MSG
+I found a #{token.humanize} at #{token.pos}
+\tbut I was in the middle of parsing a queue_group statement, and
+\twhat I really wanted was an identifier to store the queue group.
+\tSomething like: queue_group control_loops.Drivetrain my_cool_group;
+\tWot.Wot
+ERROR_MSG
+ end).data
+ obj = QueueGroupStmt.new(type_name,name).set_line(line)
+ if(tokens.peak == :tDot)
+ tokens.qError(<<ERROR_MSG)
+Hey! It looks like you're trying to use a complex identifier at: #{tokens.pos}
+\tThats not going to work. Queue Group definitions have to be of the form:
+\tqueue_group ComplexID SimpleID
+\tWot. Wot.
+ERROR_MSG
+ end
+ end
+ tokens.expect(:tSemi) do |token|
+ token.pos
+ end
+ return obj
+ end
+end
diff --git a/aos/build/queues/objects/tokenizer.rb b/aos/build/queues/objects/tokenizer.rb
new file mode 100644
index 0000000..2a33b90
--- /dev/null
+++ b/aos/build/queues/objects/tokenizer.rb
@@ -0,0 +1,213 @@
+class BufferedReader
+ def initialize(file)
+ @file = file
+ @line = 1
+ @chars = []
+ @col_nums = []
+ @col = 0
+ end
+ def filename
+ return File.basename(@file.path)
+ end
+ def pos()
+ "#{filename()}:#{lineno()},#{@col}"
+ end
+ def clear_comment()
+ @file.gets
+ @line += 1
+ end
+ def lineno()
+ return @line
+ return @file.lineno + 1
+ end
+ def pop_char()
+ val = @chars.pop() || @file.read(1)
+ @col_nums[@line] = @col += 1
+ if(val == "\n")
+ @line += 1
+ @col = 0
+ end
+
+ return val
+ end
+ def unpop_char(char)
+ if(char == "\n")
+ @line -= 1
+ @col = @col_nums[@line]
+ end
+ @col -= 1
+ @chars.push(char)
+ end
+end
+class Tokenizer
+ TOKEN_TYPES = {"{" => :tOpenB,"}"=> :tCloseB,";" => :tSemi,"," => :tComma,
+ "(" => :tOpenParan,")" => :tCloseParan,"=" => :tAssign,"." => :tDot,
+ "<<"=> :tLShift,"*" => :tMult,"+" => :tAdd,"[" => :tOpenB,
+ "]" => :tCloseB}
+ Humanize = TOKEN_TYPES.invert
+ class Token
+ attr_accessor :type,:data,:pos
+ def to_s
+ if(@type == :tString)
+ val = @data.inspect.to_s
+ elsif(@type == :tWord)
+ val = @data.to_s
+ else
+ val = @data.to_s
+ end
+ return "#{val.ljust(50)}:#{@type}"
+ end
+ def humanize()
+ if(@type == :tString)
+ return "#{@data.inspect.to_s} string"
+ elsif(@type == :tWord)
+ return "#{@data.inspect} identifier"
+ end
+ return Humanize[@type].inspect
+ end
+ def inspect()
+ data = ""
+ data = " #{@data.inspect}" if(@data)
+ "<Token :#{@type}#{data} at #{@pos}>"
+ end
+ def ==(other)
+ if(other.class == Symbol)
+ return @type == other
+ elsif(other.class == self.class)
+ return @type == other.type && @data == other.data
+ else
+ return nil
+ end
+ end
+ end
+ def initialize(file)
+ file = File.open(file,"r") if(file.class == String)
+ @read = BufferedReader.new(file)
+ end
+ def qError(error)
+ syntax_error(error)
+ end
+ def syntax_error(msg)
+ err = QSyntaxError.new(msg)
+ err.qstacktrace << "#{@read.lineno} of #{@read.filename}"
+ raise err
+ end
+ def peak_token()
+ @peak_token = next_token()
+ end
+ def peak()
+ peak_token()
+ end
+ def next()
+ next_token()
+ end
+ def pos()
+ @read.pos
+ end
+ def tokenize(string_token)
+ token = Token.new()
+ token.type = TOKEN_TYPES[string_token]
+ return token
+ end
+ def next_token()
+ if(token = @peak_token)
+ @peak_token = nil
+ return token
+ end
+ token = next_token_cache()
+ pos = self.pos()
+ token.pos = pos
+ return token
+ end
+ def next_token_cache()
+ token = Token.new()
+ token.data = ""
+ while (char = @read.pop_char())
+ #puts "#{char.inspect}:#{token.inspect}"
+ if(char == "/")
+ if(@read.pop_char == "/")
+ @read.clear_comment()
+ else
+ syntax_error("unexpected #{char.inspect}")
+ end
+ elsif(char == "#")
+ @read.clear_comment()
+ elsif(char =~ /[\s\r\n]/)
+ if(token.type)
+ return token
+ end
+ elsif(char =~ /\"/)
+ token.type = :tString
+ token.data = ""
+ while((char = @read.pop_char) != "\"")
+ token.data += char
+ end
+ return token
+ elsif(char =~ /[1-9]/)
+ token.type = :tNumber
+ token.data = char.to_i
+ while(char != ".")
+ char = @read.pop_char
+ if(char =~ /[0-9]/)
+ token.data = char.to_i + token.data * 10
+ elsif(char == ".")
+ else
+ @read.unpop_char(char)
+ return token
+ end
+ end
+ second_char = 0
+ man = 0
+ while(true)
+ char = @read.pop_char
+ if(char =~ /[0-9]/)
+ second_char = char.to_i + second_char * 10
+ man = man * 10
+ else
+ @read.unpop_char(char)
+ token.data += second_char / man.to_f
+ return token
+ end
+ end
+ elsif(char == ":")
+ if(@read.pop_char == "=")
+ return tokenize(":=")
+ end
+ syntax_error("unexpected \":\"")
+ elsif(char =~ /[;\{\}=()\",\*\+\.\[\]]/)
+ return(tokenize(char))
+ elsif(char =~ /[a-zA-Z_]/)
+ token.type = :tWord
+ token.data = char
+ while(true)
+ char = @read.pop_char()
+ if(char && char =~ /\w/)
+ token.data += char
+ else
+ @read.unpop_char(char)
+ return token
+ end
+ end
+ elsif(char == "<")
+ if((char = @read.pop_char()) == "<")
+ return tokenize("<<")
+ else
+ @read.unpop_char(char)
+ return tokenize("<")
+ end
+ else
+ syntax_error("unexpected #{char.inspect}")
+ end
+ end
+ token.type = :tEnd
+ return token
+ end
+ def expect(type,&blk)
+ token = self.next
+ if(token != type)
+ syntax_error(blk.call(token)) if(blk)
+ syntax_error("unexpected: #{token.type}")
+ end
+ return token
+ end
+end
diff --git a/aos/build/queues/output/message_dec.rb b/aos/build/queues/output/message_dec.rb
new file mode 100644
index 0000000..0e957be
--- /dev/null
+++ b/aos/build/queues/output/message_dec.rb
@@ -0,0 +1,277 @@
+require "sha1"
+class Target::MessageDec < Target::Node
+ attr_accessor :name,:loc,:parent,:msg_hash
+ def initialize(name)
+ @name = name
+ @members = []
+ end
+ def extern=(value)
+ @extern=value
+ end
+ def get_name()
+ if(@parent)
+ return "#{@parent.get_name}.#{@name}"
+ else
+ return "#{@name}"
+ end
+ end
+ def add_member(member)
+ @members << member
+ end
+ def create_Print(type_class,cpp_tree)
+ member_func = CPP::MemberFunc.new(type_class,"size_t","Print")
+ type_class.add_member(member_func)
+ member_func.args << "char *buffer"
+ member_func.args << "size_t length"
+ member_func.const = true
+ format = "\""
+ args = []
+ @members.each do |elem|
+ format += ", "
+ format += elem.toPrintFormat()
+ if (elem.type == 'bool')
+ args.push("#{elem.name} ? 't' : 'f'")
+ else
+ args.push(elem.name)
+ end
+ end
+ format += "\""
+ member_func.suite << "size_t super_size = ::aos::Message::Print(buffer, length)"
+ member_func.suite << "buffer += super_size"
+ member_func.suite << "length -= super_size"
+ member_func.suite << "return super_size + snprintf(buffer, length, " + ([format] + args).join(", ") + ")";
+ end
+ def create_Serialize(type_class,cpp_tree)
+ member_func = CPP::MemberFunc.new(type_class,"size_t","Serialize")
+ type_class.add_member(member_func)
+ #cpp_tree.cc_file.add_funct(member_func)
+ member_func.args << "char *buffer"
+ member_func.suite << "::aos::Message::Serialize(buffer)"
+ member_func.const = true
+ offset = 0
+ @members.each do |elem|
+ elem.toNetwork(offset,member_func.suite)
+ offset += elem.size;
+ end
+ member_func.suite << "return Size()"
+ end
+ def create_Deserialize(type_class,cpp_tree)
+ member_func = CPP::MemberFunc.new(type_class,"size_t","Deserialize")
+ type_class.add_member(member_func)
+ #cpp_tree.cc_file.add_funct(member_func)
+ member_func.args << "const char *buffer"
+ member_func.suite << "::aos::Message::Deserialize(buffer)"
+ offset = 0
+ @members.each do |elem|
+ elem.toHost(offset,member_func.suite)
+ offset += elem.size;
+ end
+ member_func.suite << "return Size()"
+ end
+ def create_Zero(type_class,cpp_tree)
+ member_func = CPP::MemberFunc.new(type_class,"void","Zero")
+ type_class.add_member(member_func)
+ #cpp_tree.cc_file.add_funct(member_func)
+ @members.each do |elem|
+ elem.zeroCall(member_func.suite)
+ end
+ member_func.suite << "::aos::Message::Zero()"
+ end
+ def create_Size(type_class,cpp_tree)
+ member_func = CPP::MemberFunc.new(type_class,"size_t","Size")
+ member_func.inline = true
+ member_func.static = true
+ type_class.add_member(member_func.forward_dec)
+ #cpp_tree.cc_file.add_funct(member_func)
+ size = 0
+ @members.each do |elem|
+ size += elem.size
+ end
+ member_func.suite << CPP::Return.new(CPP::Add.new(size,
+ "::aos::Message::Size()"))
+ end
+ def self.builder_loc(loc)
+ return @builder_loc if(@builder_loc)
+ return @builder_loc = loc.root.get_make("aos")
+ end
+ def type_name(builder_loc,name)
+ if(builder_loc == @loc) #use relative name
+ return name
+ else #use full name
+ return @loc.to_cpp_id(name)
+ end
+ end
+ def create(cpp_tree)
+ return self if(@extern)
+ orig_namespace = namespace = cpp_tree.get(@loc)
+ name = ""
+ if(namespace.class < Types::Type) #is nested
+ name = namespace.name + "_" + name
+ namespace = namespace.space
+ end
+ type_class = namespace.add_struct(name + @name)
+ if(name.length > 0)
+ orig_namespace.add_member(:public, Types::TypeDef.new(type_class,@name))
+ end
+ cpp_tree.set(self,type_class)
+ type_class.set_parent("public ::aos::Message")
+ ts = (@members.collect { |elem|
+ elem.type + " " + elem.name
+ }).join(";")
+ self.msg_hash = "0x#{SHA1.hexdigest(ts)[-8..-1]}"
+ type_class.add_member("enum {kQueueLength = 1234, kHash = #{self.msg_hash}}")
+ @members.each do |elem|
+ type_class.add_member(elem.create_usage(cpp_tree))
+ end
+
+ create_Serialize(type_class,cpp_tree)
+ create_Deserialize(type_class,cpp_tree)
+ create_Zero(type_class,cpp_tree)
+ create_Size(type_class,cpp_tree)
+ create_Print(type_class,cpp_tree)
+
+ b_namespace = cpp_tree.get(b_loc = self.class.builder_loc(@loc))
+
+ safetemplate = Types::TemplateClass.new(b_namespace,"SafeMessageBuilder")
+ ifdef_statement = Types::PreprocessorIf.new(b_namespace,"!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)")
+ ifdef_statement.add_member(safetemplate)
+ b_namespace.add(ifdef_statement)
+ template = b_namespace.add_template("MessageBuilder")
+ safetemplate.spec_args << t = @loc.to_cpp_id(@name)
+ template.spec_args << t = @loc.to_cpp_id(@name)
+ safemsg_ptr_t = "SafeScopedMessagePtr< #{t}>"
+ msg_ptr_t = "ScopedMessagePtr< #{t}>"
+ safemsg_bld_t = "SafeMessageBuilder< #{t}>"
+ msg_bld_t = "MessageBuilder< #{t}>"
+ safetemplate.add_member(:private,"#{safemsg_ptr_t} msg_ptr_")
+ template.add_member(:private,"#{msg_ptr_t} msg_ptr_")
+ namespace.add_pre_swig("%feature(\"valuewrapper\") #{safemsg_bld_t}")
+ template.add_member(:private,"#{msg_bld_t}(const #{msg_bld_t}&)")
+ template.add_member(:private,"void operator=(const #{msg_bld_t}&)")
+ safetemplate.add_member(:private,"friend class ::aos::Queue< #{t}>")
+ template.add_member(:private,"friend class ::aos::Queue< #{t}>")
+
+ cons = CPP::Constructor.new(template)
+ unsafe_cons = CPP::Constructor.new(template)
+ cons_ifdef_statement = CPP::PreprocessorIf.new(cons, unsafe_cons)
+ cons_ifdef_statement.name = "!defined(__VXWORKS__) && !defined(__TEST_VXWORKS__)"
+ template.add_member(:private,cons_ifdef_statement)
+ cons.args << "aos_queue *queue"
+ cons.args << "#{t} *msg"
+ unsafe_cons.args << "#{t} *msg"
+ cons.add_cons("msg_ptr_","queue","msg")
+ unsafe_cons.add_cons("msg_ptr_","msg")
+ cons = safetemplate.add_member(:private,CPP::Constructor.new(safetemplate))
+ cons.args << "aos_queue *queue"
+ cons.add_cons("msg_ptr_","queue")
+ safetemplate.public
+ template.public
+ DefineMembers(cpp_tree, safetemplate, safemsg_bld_t)
+ DefineMembers(cpp_tree, template, msg_bld_t)
+
+ java_type_name = java_type_name(cpp_tree)
+ namespace.add_post_swig("%template(#{java_type_name}) ::aos::Queue< #{t}>")
+ namespace.add_post_swig("%template(#{java_ptr_name(cpp_tree)}) ::aos::SafeScopedMessagePtr< #{t}>")
+ namespace.add_post_swig("%template(#{java_builder_name(cpp_tree)}) ::aos::SafeMessageBuilder< #{t}>")
+ # TODO(aschuh): Figure out why this doesn't work and fix it.
+ #namespace.add_post_swig("%typemap(javabase) #{@name} \"aos.Message\"")
+
+ end
+ def DefineMembers(cpp_tree, template, msg_bld_t)
+ send = template.def_func("bool","Send")
+ send.suite << CPP::Return.new("msg_ptr_.Send()")
+ @members.each do |elem|
+=begin
+ MessageBuilder<frc971::control_loops::Drivetrain::Goal> &steering(
+ double steering) {
+ msg_ptr_->steering = steering;
+ return *this;
+ }
+=end
+ setter = template.def_func(msg_bld_t,"&#{elem.name}")
+ setter.args << elem.create_usage(cpp_tree)
+ elem.set_message_builder(setter.suite)
+ setter.suite << CPP::Return.new("*this")
+
+ end
+ end
+ def java_ptr_name(cpp_tree)
+ return "#{@name}MessagePtr"
+ end
+ def java_builder_name(cpp_tree)
+ return "#{@name}MessageBuilder"
+ end
+ def java_type_name(cpp_tree)
+ return "#{@name}Queue"
+ end
+end
+class Target::MessageElement < Target::Node
+ attr_accessor :name,:loc,:size,:zero,:type,:printformat
+ def initialize(type,name)
+ @type,@name = type,name
+ end
+ def toPrintFormat()
+ return printformat
+ end
+ def create_usage(cpp_tree)
+ "#{@type} #{@name}"
+ end
+ def toNetwork(offset,suite)
+ offset = (offset == 0) ? "" : "#{offset} + "
+ suite << f_call = CPP::FuncCall.build("to_network",
+ "&#{@name}",
+ "&buffer[#{offset}::aos::Message::Size()]")
+ f_call.args.dont_wrap = true
+ end
+ def toHost(offset,suite)
+ offset = (offset == 0) ? "" : "#{offset} + "
+ suite << f_call = CPP::FuncCall.build("to_host",
+ "&buffer[#{offset}::aos::Message::Size()]",
+ "&#{@name}")
+ f_call.args.dont_wrap = true
+ end
+ def set_message_builder(suite)
+ suite << "msg_ptr_->#{@name} = #{@name}"
+ end
+
+ def zeroCall(suite)
+ suite << CPP::Assign.new(@name,@zero)
+ end
+end
+class Target::MessageArrayElement < Target::Node
+ attr_accessor :name,:loc,:size,:zero,:type
+ def initialize(type,name,length)
+ @type,@name,@length = type,name,length
+ end
+ def create_usage(cpp_tree)
+ "#{@type} #{@name}[#@length]"
+ end
+ def type()
+ "#{@type}[#@length]"
+ end
+ def size()
+ @size * @length
+ end
+ def toNetwork(offset,suite)
+ offset = (offset == 0) ? "" : "#{offset} + "
+ suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
+ for_stmt.suite << f_call = CPP::FuncCall.build("to_network",
+ "&(#{@name}[i])",
+ "&buffer[i + #{offset}::aos::Message::Size()]")
+ f_call.args.dont_wrap = true
+ end
+ def toHost(offset,suite)
+ offset = (offset == 0) ? "" : "#{offset} + "
+ suite << for_stmt = CPP::For.new("int i = 0","i < #{@length}","i++")
+ for_stmt.suite << f_call = CPP::FuncCall.build("to_host",
+ "&buffer[i + #{offset}::aos::Message::Size()]",
+ "&(#{@name}[i])")
+ f_call.args.dont_wrap = true
+ end
+ def set_message_builder(suite)
+ suite << "memcpy(msg_ptr_->#{@name},#{@name},#@length)"
+ end
+ def zeroCall(suite)
+ suite << "memset(#@name,0,#{size()})"
+ end
+end
diff --git a/aos/build/queues/output/q_file.rb b/aos/build/queues/output/q_file.rb
new file mode 100644
index 0000000..af76ee1
--- /dev/null
+++ b/aos/build/queues/output/q_file.rb
@@ -0,0 +1,187 @@
+require "sha1"
+module Target
+end
+class Target::Node
+ attr_accessor :created_by
+end
+class Target::QFile < Target::Node
+ def initialize() #needs to know repo_path,
+ @class_types = []
+ end
+ def add_type(type)
+ @class_types << type
+ end
+ def extern=(value)
+ @class_types.each do |type|
+ type.extern=value
+ end
+ end
+ def make_cpp_tree(rel_path)
+ cpp_tree = DepFilePair.new(rel_path)
+ cpp_tree.add_header_include("\"aos/common/macros.h\"")
+ cpp_tree.add_header_include("\"aos/common/queue.h\"")
+ @class_types.each do |type|
+ cpp_tree.get(type)
+ end
+ return cpp_tree
+ end
+end
+class Target::QInclude < Target::Node
+ def initialize(path)
+ @path = path
+ end
+ def create(cpp_tree)
+# inc = cpp_tree.header.add_include("\"#{@path}\"")
+ inc = cpp_tree.add_header_include("\"#{@path}\"")
+ cpp_tree.set(self,inc)
+ end
+end
+class Target::QueueGroupDec < Target::Node
+ attr_accessor :name,:loc,:parent,:queues
+ def initialize(name)
+ @name = name
+ @queues = []
+ @subs = {}
+ end
+ def root()
+ @parent.root()
+ end
+ def []=(key,val)
+ #puts "#{key}= #{val}"
+ @subs[key] = val
+ end
+ def extern=(value)
+ @extern=value
+ end
+ def get_name()
+ if(@parent)
+ return "#{@parent.get_name}.#{@name}"
+ else
+ return "#{@name}"
+ end
+ end
+ def to_cpp_id(id)
+ name = "#{@name}::#{id}"
+ return @parent.to_cpp_id(name) if(@parent)
+ return name
+ end
+ def [](key)
+ #puts "#{key}"
+ @subs[key]
+ end
+ def add_queue(queue)
+ @queues.push(queue)
+ end
+ def hash_with_name(name)
+ ts = (@queues.collect { |queue|
+ queue.msg_hash()
+ }).join("") + name
+ return "0x#{SHA1.hexdigest(ts)[-8..-1]}"
+ end
+ def create(cpp_tree)
+ return if(@extern)
+ namespace = cpp_tree.get(@loc)
+ type_class = Types::Class.new(namespace,@name)
+ cpp_tree.set(self,type_class) #breaks infinite recursion
+ type_class.set_parent("public ::aos::QueueGroup")
+ @queues.each do |queue|
+ type_class.add_member(:public,queue.create_usage(cpp_tree))
+ namespace.add_pre_swig("%immutable #{@name}::#{queue.name}")
+ end
+ create_Constructor(type_class,cpp_tree)
+ namespace.add(type_class)
+ end
+ def create_Constructor(type_class,cpp_tree)
+ member_func = CPP::Constructor.new(type_class)
+ type_class.add_member(:public,member_func)
+ #cpp_tree.cc_file.add_funct(member_func)
+ member_func.args << "const char *name";
+ member_func.args << "uint32_t hash";
+ member_func.add_cons("::aos::QueueGroup","name", "hash")
+ @queues.each do |queue|
+ member_func.args << "const char *#{queue.name}_name";
+ member_func.add_cons(queue.name,"#{queue.name}_name")
+ end
+ end
+end
+class Target::QueueGroup < Target::Node
+ attr_accessor :name,:loc
+ def initialize(type,name)
+ @type,@name = type,name
+ end
+ def type_name()
+ if(@type.loc == @loc) #use relative name
+ return @type.name
+ else #use full name
+ return @type.loc.to_cpp_id(@type.name)
+ end
+ end
+ def create(cpp_tree)
+ namespace = cpp_tree.get(@loc)
+ type = cpp_tree.get(@type)
+ cpp_tree.set(self,self)
+ namespace.add_cc("static #{type_name} *#{@name}_ptr")
+ counter = "#{@name}_counter"
+ namespace.add_cc("static int #{counter}")
+
+ str = <<COMMENT_END
+Schwarz counter to construct and destruct the #{@name} object.
+Must be constructed before &#{@name} is constructed so that #{@name}_ptr
+is valid so we can store a reference to the object.
+COMMENT_END
+ str.split(/\n/).each do |str_sec|
+ namespace.class_comment(str_sec)
+ end
+ init_class = namespace.add_class("InitializerFor_" + @name).add_dep(type)
+
+
+ init_class.add_cc_comment(
+ "The counter is initialized at load-time, i.e., before any of the static",
+ "objects are initialized.")
+
+
+ cons = CPP::Constructor.new(init_class)
+ init_class.add_member(:public,cons)
+ cons.suite << if_stmt = CPP::If.new("0 == #{counter}++")
+ if_stmt.suite << "printf(#{"making a #{@name}!\n".inspect})"
+
+ cons_call = CPP::FuncCall.new("new #{type_name}")
+ cons_call.args.push(@loc.queue_name(@name).inspect)
+
+ cons_call.args.push(@type.hash_with_name(@loc.queue_name(@name).inspect))
+ @type.queues.collect do |queue|
+ cons_call.args.push(@loc.queue_name(@name + "." + queue.name).inspect)
+ end
+ if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call)
+ if_stmt.else_suite << CPP::FuncCall.build("printf","already made a #{@name}\n".inspect)
+
+
+ destruct = CPP::Destructor.new(init_class)
+ destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}")
+ if_stmt.suite << "printf(#{"deleting a #{@name}!! :) !!\n".inspect})"
+ if_stmt.suite << "delete #{@name}_ptr"
+ if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL")
+
+ init_class.add_member(:public,destruct)
+ init_class.static = true
+ init_class.dec = @name + "_initializer";
+
+ str = <<COMMENT_END
+Create a reference to the new object in the pointer. Since we have already
+created the initializer
+COMMENT_END
+ comments = str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)}
+ comments << "static UNUSED_VARIABLE #{type_name} &#{@name} = " +
+ "#{@name}_initializer.get()"
+ namespace.add_post_swig("%immutable #{@name}_initializer")
+ namespace.add_post_swig(CPP::SwigPragma.new("java", "modulecode", CPP::Suite.new(["public static final #{@name} = get#{@name.capitalize}_initializer().get()"])))
+ ifdef_statement = CPP::IfnDef.new(CPP::Suite.new(comments))
+ ifdef_statement.name = "SWIG"
+ namespace.add(ifdef_statement)
+
+
+ get = init_class.def_func(type_name,"get") #.add_dep(type)
+ get.pre_func_types = "&"
+ get.suite << CPP::Return.new("*#{@name}_ptr")
+ end
+end
diff --git a/aos/build/queues/output/queue_dec.rb b/aos/build/queues/output/queue_dec.rb
new file mode 100644
index 0000000..8c3bd51
--- /dev/null
+++ b/aos/build/queues/output/queue_dec.rb
@@ -0,0 +1,104 @@
+class Target::QueueDec < Target::Node
+ attr_accessor :name,:loc
+ def initialize(type,name)
+ @type,@name = type,name
+ end
+ def msg_hash()
+ return @type.msg_hash
+ end
+ def java_type_name(cpp_tree)
+ type = cpp_tree.get(@type)
+ return "#{type.name}Queue"
+ end
+ def full_message_name(cpp_tree)
+ type = cpp_tree.get(@type)
+ return @type.loc.to_cpp_id(type.name)
+ end
+ def full_ptr_name(cpp_tree)
+ return "::aos::SafeScopedMessagePtr< #{full_message_name(cpp_tree)}>"
+ end
+ def full_builder_name(cpp_tree)
+ return "::aos::MessageBuilder< #{full_message_name(cpp_tree)}>"
+ end
+ def full_type_name(cpp_tree)
+ return "::aos::Queue< #{full_message_name(cpp_tree)}>"
+ end
+ def type_name(cpp_tree,queue_type = "::aos::Queue")
+ type = cpp_tree.get(@type)
+ if(@type.loc == @loc) #use relative name
+ return "#{queue_type}<#{type.name}>"
+ else #use full name
+ return "#{queue_type}< #{@type.loc.to_cpp_id(type.name)}>"
+ end
+ end
+ def create_usage(cpp_tree)
+ "#{type_name(cpp_tree)} #{@name}"
+ end
+ def create(cpp_tree)
+ namespace = cpp_tree.get(@loc)
+ type = cpp_tree.get(@type)
+ cpp_tree.set(self,self)
+ type_name = type_name(cpp_tree)
+ full_type_name = full_type_name(cpp_tree)
+ namespace.add_cc("static #{type_name} *#{@name}_ptr")
+ counter = "#{@name}_counter"
+ namespace.add_cc("static int #{counter}")
+
+ str = <<COMMENT_END
+Schwarz counter to construct and destruct the #{@name} queue.
+Must be constructed before &#{@name} is constructed so that #{@name}_ptr
+is valid so we can store a reference to the object.
+COMMENT_END
+ str.split(/\n/).each do |str_sec|
+ namespace.class_comment(str_sec)
+ end
+ init_class = namespace.add_class("InitializerFor_" + @name)
+
+ init_class.add_cc_comment(
+ "The counter is initialized at load-time, i.e., before any of the static",
+ "objects are initialized.")
+
+
+ cons = CPP::Constructor.new(init_class)
+ init_class.add_member(:public,cons)
+ cons.suite << if_stmt = CPP::If.new("0 == #{counter}++")
+ if_stmt.suite << "printf(#{"making a #{@name} queue!\n".inspect})"
+
+ cons_call = CPP::FuncCall.new("new #{type_name}")
+ cons_call.args.push(@loc.queue_name(@name).inspect)
+ if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call)
+ if_stmt.else_suite << CPP::FuncCall.build("printf","already made a #{@name}\n".inspect)
+
+
+ destruct = CPP::Destructor.new(init_class)
+ init_class.add_member(:public,destruct)
+ destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}")
+ if_stmt.suite << "printf(#{"deleting a #{@name}!! :) !!\n".inspect})"
+ if_stmt.suite << "delete #{@name}_ptr"
+ if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL")
+
+ init_class.static = true
+ init_class.dec = @name + "_initializer";
+
+ str = <<COMMENT_END
+Create a reference to the new object in the pointer. Since we have already
+created the initializer
+COMMENT_END
+ comments = str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)}
+ comments << "static UNUSED_VARIABLE #{type_name} &#{@name} = " +
+ "#{@name}_initializer.get()"
+ namespace.add_post_swig("%immutable #{@name}_initializer")
+ java_type_name = java_type_name(cpp_tree)
+ namespace.add_post_swig(CPP::SwigPragma.new("java", "modulecode", CPP::Suite.new(["public static final #{java_type_name} #{@name} = get#{@name.capitalize}_initializer().get()"])))
+
+ ifdef_statement = CPP::IfnDef.new(CPP::Suite.new(comments))
+ ifdef_statement.name = "SWIG"
+ namespace.add(ifdef_statement)
+
+ get = init_class.def_func(full_type_name,"get")
+ get.pre_func_types = "&"
+ get.suite << CPP::Return.new("*#{@name}_ptr")
+
+ end
+end
+