blob: af76ee16cdf4cac3ed0a2676f2d3bcdef057f10e [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001require "sha1"
2module Target
3end
4class Target::Node
5 attr_accessor :created_by
6end
7class Target::QFile < Target::Node
8 def initialize() #needs to know repo_path,
9 @class_types = []
10 end
11 def add_type(type)
12 @class_types << type
13 end
14 def extern=(value)
15 @class_types.each do |type|
16 type.extern=value
17 end
18 end
19 def make_cpp_tree(rel_path)
20 cpp_tree = DepFilePair.new(rel_path)
21 cpp_tree.add_header_include("\"aos/common/macros.h\"")
22 cpp_tree.add_header_include("\"aos/common/queue.h\"")
23 @class_types.each do |type|
24 cpp_tree.get(type)
25 end
26 return cpp_tree
27 end
28end
29class Target::QInclude < Target::Node
30 def initialize(path)
31 @path = path
32 end
33 def create(cpp_tree)
34# inc = cpp_tree.header.add_include("\"#{@path}\"")
35 inc = cpp_tree.add_header_include("\"#{@path}\"")
36 cpp_tree.set(self,inc)
37 end
38end
39class Target::QueueGroupDec < Target::Node
40 attr_accessor :name,:loc,:parent,:queues
41 def initialize(name)
42 @name = name
43 @queues = []
44 @subs = {}
45 end
46 def root()
47 @parent.root()
48 end
49 def []=(key,val)
50 #puts "#{key}= #{val}"
51 @subs[key] = val
52 end
53 def extern=(value)
54 @extern=value
55 end
56 def get_name()
57 if(@parent)
58 return "#{@parent.get_name}.#{@name}"
59 else
60 return "#{@name}"
61 end
62 end
63 def to_cpp_id(id)
64 name = "#{@name}::#{id}"
65 return @parent.to_cpp_id(name) if(@parent)
66 return name
67 end
68 def [](key)
69 #puts "#{key}"
70 @subs[key]
71 end
72 def add_queue(queue)
73 @queues.push(queue)
74 end
75 def hash_with_name(name)
76 ts = (@queues.collect { |queue|
77 queue.msg_hash()
78 }).join("") + name
79 return "0x#{SHA1.hexdigest(ts)[-8..-1]}"
80 end
81 def create(cpp_tree)
82 return if(@extern)
83 namespace = cpp_tree.get(@loc)
84 type_class = Types::Class.new(namespace,@name)
85 cpp_tree.set(self,type_class) #breaks infinite recursion
86 type_class.set_parent("public ::aos::QueueGroup")
87 @queues.each do |queue|
88 type_class.add_member(:public,queue.create_usage(cpp_tree))
89 namespace.add_pre_swig("%immutable #{@name}::#{queue.name}")
90 end
91 create_Constructor(type_class,cpp_tree)
92 namespace.add(type_class)
93 end
94 def create_Constructor(type_class,cpp_tree)
95 member_func = CPP::Constructor.new(type_class)
96 type_class.add_member(:public,member_func)
97 #cpp_tree.cc_file.add_funct(member_func)
98 member_func.args << "const char *name";
99 member_func.args << "uint32_t hash";
100 member_func.add_cons("::aos::QueueGroup","name", "hash")
101 @queues.each do |queue|
102 member_func.args << "const char *#{queue.name}_name";
103 member_func.add_cons(queue.name,"#{queue.name}_name")
104 end
105 end
106end
107class Target::QueueGroup < Target::Node
108 attr_accessor :name,:loc
109 def initialize(type,name)
110 @type,@name = type,name
111 end
112 def type_name()
113 if(@type.loc == @loc) #use relative name
114 return @type.name
115 else #use full name
116 return @type.loc.to_cpp_id(@type.name)
117 end
118 end
119 def create(cpp_tree)
120 namespace = cpp_tree.get(@loc)
121 type = cpp_tree.get(@type)
122 cpp_tree.set(self,self)
123 namespace.add_cc("static #{type_name} *#{@name}_ptr")
124 counter = "#{@name}_counter"
125 namespace.add_cc("static int #{counter}")
126
127 str = <<COMMENT_END
128Schwarz counter to construct and destruct the #{@name} object.
129Must be constructed before &#{@name} is constructed so that #{@name}_ptr
130is valid so we can store a reference to the object.
131COMMENT_END
132 str.split(/\n/).each do |str_sec|
133 namespace.class_comment(str_sec)
134 end
135 init_class = namespace.add_class("InitializerFor_" + @name).add_dep(type)
136
137
138 init_class.add_cc_comment(
139 "The counter is initialized at load-time, i.e., before any of the static",
140 "objects are initialized.")
141
142
143 cons = CPP::Constructor.new(init_class)
144 init_class.add_member(:public,cons)
145 cons.suite << if_stmt = CPP::If.new("0 == #{counter}++")
146 if_stmt.suite << "printf(#{"making a #{@name}!\n".inspect})"
147
148 cons_call = CPP::FuncCall.new("new #{type_name}")
149 cons_call.args.push(@loc.queue_name(@name).inspect)
150
151 cons_call.args.push(@type.hash_with_name(@loc.queue_name(@name).inspect))
152 @type.queues.collect do |queue|
153 cons_call.args.push(@loc.queue_name(@name + "." + queue.name).inspect)
154 end
155 if_stmt.suite << CPP::Assign.new("#{@name}_ptr",cons_call)
156 if_stmt.else_suite << CPP::FuncCall.build("printf","already made a #{@name}\n".inspect)
157
158
159 destruct = CPP::Destructor.new(init_class)
160 destruct.suite << if_stmt = CPP::If.new("0 == --#{counter}")
161 if_stmt.suite << "printf(#{"deleting a #{@name}!! :) !!\n".inspect})"
162 if_stmt.suite << "delete #{@name}_ptr"
163 if_stmt.suite << CPP::Assign.new("#{@name}_ptr","NULL")
164
165 init_class.add_member(:public,destruct)
166 init_class.static = true
167 init_class.dec = @name + "_initializer";
168
169 str = <<COMMENT_END
170Create a reference to the new object in the pointer. Since we have already
171created the initializer
172COMMENT_END
173 comments = str.split(/\n/).map{|str_sec| CPP::Comment.new(str_sec)}
174 comments << "static UNUSED_VARIABLE #{type_name} &#{@name} = " +
175 "#{@name}_initializer.get()"
176 namespace.add_post_swig("%immutable #{@name}_initializer")
177 namespace.add_post_swig(CPP::SwigPragma.new("java", "modulecode", CPP::Suite.new(["public static final #{@name} = get#{@name.capitalize}_initializer().get()"])))
178 ifdef_statement = CPP::IfnDef.new(CPP::Suite.new(comments))
179 ifdef_statement.name = "SWIG"
180 namespace.add(ifdef_statement)
181
182
183 get = init_class.def_func(type_name,"get") #.add_dep(type)
184 get.pre_func_types = "&"
185 get.suite << CPP::Return.new("*#{@name}_ptr")
186 end
187end