blob: 78414119fd3ed7a03b2a940a6f25b9b04fec87b5 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001class MessageElementStmt < QStmt
2 attr_accessor :name
Parker Schuh343481e2014-02-09 18:28:43 -08003 def initialize(type_name,name,length = nil) #lengths are for arrays
4 @type_name = type_name
5 @type = type_name.to_s
Austin Schuhbccac532016-12-10 13:51:35 -08006 @type = '::aos::monotonic_clock::time_point' if @type == 'Time'
brians343bc112013-02-10 01:53:46 +00007 @name = name
8 @length = length
9 end
Brian Silverman96e6d5a2014-03-24 15:55:40 -070010 CommonMistakes = {"short" => "int16_t","int" => "int32_t","long" => "int64_t","time" => "Time"}
Parker Schuh343481e2014-02-09 18:28:43 -080011 def check_type_error(locals)
brians343bc112013-02-10 01:53:46 +000012 if(!(Sizes[@type] || (@length != nil && @type == "char")) )
13 if(correction = CommonMistakes[@type])
14 raise QError.new(<<ERROR_MSG)
15Hey! you have a \"#{@type}\" in your message statement.
16\tplease use #{correction} instead. Your type is not supported because we
17\twant to guarantee that the sizes of the messages stay the same across platforms.
18\tWot. Wot.
19ERROR_MSG
20 elsif(@type == "char")
21 raise QError.new(<<ERROR_MSG)
22Hey! you have a \"#{@type}\" in your message statement.
23\tyou need your declaration to be a char array like: char[10].
24\tor, please use int8_t or uint8_t.
25\tWot. Wot.
26ERROR_MSG
27 else
Parker Schuh343481e2014-02-09 18:28:43 -080028 @is_struct_type = true
29 return if(lookup_type(locals))
brians343bc112013-02-10 01:53:46 +000030 raise QError.new(<<ERROR_MSG)
31Hey! you have a \"#{@type}\" in your message statement.
32\tThat is not in the list of supported types.
33\there is the list of supported types:
Parker Schuh343481e2014-02-09 18:28:43 -080034\tint{8,16,32,64}_t,uint{8,16,32,64}_t,bool,float,double
brians343bc112013-02-10 01:53:46 +000035\tWot. Wot.
36ERROR_MSG
37 end
38 end
39 end
40
41 PrintFormat = {"bool" => "%c",
42 "float" => "%f",
43 "char" => "%c",
44 "double" => "%f",
Brian Silverman8efe23e2013-07-07 23:31:37 -070045 "uint8_t" => "%\" PRIu8 \"",
46 "uint16_t" => "%\" PRIu16 \"",
47 "uint32_t" => "%\" PRIu32 \"",
48 "uint64_t" => "%\" PRIu64 \"",
49 "int8_t" => "%\" PRId8 \"",
50 "int16_t" => "%\" PRId16 \"",
51 "int32_t" => "%\" PRId32 \"",
Brian Silverman96e6d5a2014-03-24 15:55:40 -070052 "int64_t" => "%\" PRId64 \"",
Austin Schuhbccac532016-12-10 13:51:35 -080053 "::aos::monotonic_clock::time_point" => "\" AOS_TIME_FORMAT \""}
brians343bc112013-02-10 01:53:46 +000054 def toPrintFormat()
55 if(format = PrintFormat[@type])
56 return format;
57 end
58 raise QError.new(<<ERROR_MSG)
59Somehow this slipped past me, but
60\tI couldn't find the print format of #{@type}. Really, my bad.
61\tWot. Wot.
62ERROR_MSG
63 end
64
Austin Schuhbccac532016-12-10 13:51:35 -080065 Sizes = {"bool" => 1, "float" => 4,"double" => 8,"::aos::monotonic_clock::time_point" => 8}
brians343bc112013-02-10 01:53:46 +000066 [8,16,32,64].each do |len|
67 Sizes["int#{len}_t"] = len / 8
68 Sizes["uint#{len}_t"] = len / 8
69 end
Austin Schuhbccac532016-12-10 13:51:35 -080070 Zero = {"float" => "0.0f","double" => "0.0","bool" => "false","::aos::monotonic_clock::time_point" => "::aos::monotonic_clock::epoch()"}
brians343bc112013-02-10 01:53:46 +000071 def size()
72 if(size = Sizes[@type]); return size; end
73 return 1 if(@type == "char")
74 raise QError.new(<<ERROR_MSG)
75Somehow this slipped past me, but
76\tI couldn't find the size of #{@type}. Really, my bad.
77\tWot. Wot.
78ERROR_MSG
79 end
Parker Schuh343481e2014-02-09 18:28:43 -080080 def lookup_type(locals)
81 return @type_name.lookup(locals)
82 end
brians343bc112013-02-10 01:53:46 +000083 def q_eval(locals)
Parker Schuh343481e2014-02-09 18:28:43 -080084 check_type_error(locals)
85 if(@is_struct_type)
86 tval = lookup_type(locals)
Austin Schuh7e958392014-10-21 22:16:23 -070087 member = Target::MessageStructElement.new(tval, @name)
88 if (@length != nil)
89 inner_member = member
90 member = Target::MessageArrayElement.new(inner_member, @length)
91 end
brians343bc112013-02-10 01:53:46 +000092 else
Austin Schuh7e958392014-10-21 22:16:23 -070093 member = Target::MessageElement.new(@type,@name)
Parker Schuh343481e2014-02-09 18:28:43 -080094 member.size = size()
95 member.zero = Zero[@type] || "0";
96 member.printformat = toPrintFormat()
Austin Schuh7e958392014-10-21 22:16:23 -070097
98 if(@length != nil)
99 inner_member = member
100 member = Target::MessageArrayElement.new(inner_member,@length)
101 end
brians343bc112013-02-10 01:53:46 +0000102 end
brians343bc112013-02-10 01:53:46 +0000103 locals.local.add_member(member)
104 end
105 def self.parse(tokens)
106 line = tokens.pos
Parker Schuh343481e2014-02-09 18:28:43 -0800107 #type = tokens.expect(:tWord).data
108 type_name = QualifiedName.parse(tokens)
brians343bc112013-02-10 01:53:46 +0000109 len = nil
110 if(tokens.peak == :tOpenB)
111 tokens.expect(:tOpenB)
112 len = tokens.expect(:tNumber).data
113 tokens.expect(:tCloseB)
114 end
115 name = tokens.expect(:tWord).data
116 tokens.expect(:tSemi)
Parker Schuh343481e2014-02-09 18:28:43 -0800117 return self.new(type_name,name,len).set_line(line)
brians343bc112013-02-10 01:53:46 +0000118 end
119end
120class MessageStmt < QStmt
121 def initialize(name,suite)
122 @name = name
123 @suite = suite
124 end
125 def q_eval(locals)
126 group = Target::MessageDec.new(@name)
127 locals.register(group)
128 @suite.each do |stmt|
129 stmt.q_eval(locals.bind(group))
130 end
131 return group
132 end
133 def self.parse(tokens)
134 name = tokens.expect(:tWord).data
135 values = []
136 tokens.expect(:tOpenB)
137 while(tokens.peak != :tCloseB)
138 values << MessageElementStmt.parse(tokens)
139 end
140 names = {}
141 values.each do |val|
142 if(names[val.name])
143 raise QSyntaxError.new(<<ERROR_MSG)
144Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
145\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
146\tWot. Wot.
147ERROR_MSG
148 end
149 names[val.name] = val
150 end
151 tokens.expect(:tCloseB)
152 tokens.expect(:tSemi)
153 self.new(name,values)
154 end
155end
156class QueueStmt < QStmt
157 def initialize(type,name)
158 @type,@name = type,name
159 end
160 def q_eval(locals)
161 queue = Target::QueueDec.new(@type.lookup(locals),@name)
162 locals.register(queue)
163 locals.local.add_queue(queue) if(locals.local.respond_to?(:add_queue))
164 return queue
165 end
166 def self.parse(tokens)
167 line = tokens.pos
168 type_name = QualifiedName.parse(tokens)
169 name = tokens.expect(:tWord).data
170 tokens.expect(:tSemi)
171 return self.new(type_name,name).set_line(line)
172 end
173end