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