blob: b40ccb2d2e5c345c286791aed05e210718d44790 [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
Brian Silverman96e6d5a2014-03-24 15:55:40 -07006 @type = '::aos::time::Time' 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 \"",
53 "::aos::time::Time" => "%010\" PRId32 \".%05\" PRId32 \"s"}
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
Brian Silverman96e6d5a2014-03-24 15:55:40 -070065 Sizes = {"bool" => 1, "float" => 4,"double" => 8,"::aos::time::Time" => 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
Brian Silverman96e6d5a2014-03-24 15:55:40 -070070 Zero = {"float" => "0.0f","double" => "0.0","bool" => "false","::aos::time::Time" => "::aos::time::Time(0, 0)"}
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)
87 member = Target::MessageStructElement.new(tval, name)
brians343bc112013-02-10 01:53:46 +000088 else
Parker Schuh343481e2014-02-09 18:28:43 -080089 if(@length == nil)
90 member = Target::MessageElement.new(@type,@name)
91 else
92 member = Target::MessageArrayElement.new(@type,@name,@length)
93 end
94 member.size = size()
95 member.zero = Zero[@type] || "0";
96 member.printformat = toPrintFormat()
brians343bc112013-02-10 01:53:46 +000097 end
brians343bc112013-02-10 01:53:46 +000098 locals.local.add_member(member)
99 end
100 def self.parse(tokens)
101 line = tokens.pos
Parker Schuh343481e2014-02-09 18:28:43 -0800102 #type = tokens.expect(:tWord).data
103 type_name = QualifiedName.parse(tokens)
brians343bc112013-02-10 01:53:46 +0000104 len = nil
105 if(tokens.peak == :tOpenB)
106 tokens.expect(:tOpenB)
107 len = tokens.expect(:tNumber).data
108 tokens.expect(:tCloseB)
109 end
110 name = tokens.expect(:tWord).data
111 tokens.expect(:tSemi)
Parker Schuh343481e2014-02-09 18:28:43 -0800112 return self.new(type_name,name,len).set_line(line)
brians343bc112013-02-10 01:53:46 +0000113 end
114end
115class MessageStmt < QStmt
116 def initialize(name,suite)
117 @name = name
118 @suite = suite
119 end
120 def q_eval(locals)
121 group = Target::MessageDec.new(@name)
122 locals.register(group)
123 @suite.each do |stmt|
124 stmt.q_eval(locals.bind(group))
125 end
126 return group
127 end
128 def self.parse(tokens)
129 name = tokens.expect(:tWord).data
130 values = []
131 tokens.expect(:tOpenB)
132 while(tokens.peak != :tCloseB)
133 values << MessageElementStmt.parse(tokens)
134 end
135 names = {}
136 values.each do |val|
137 if(names[val.name])
138 raise QSyntaxError.new(<<ERROR_MSG)
139Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
140\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
141\tWot. Wot.
142ERROR_MSG
143 end
144 names[val.name] = val
145 end
146 tokens.expect(:tCloseB)
147 tokens.expect(:tSemi)
148 self.new(name,values)
149 end
150end
151class QueueStmt < QStmt
152 def initialize(type,name)
153 @type,@name = type,name
154 end
155 def q_eval(locals)
156 queue = Target::QueueDec.new(@type.lookup(locals),@name)
157 locals.register(queue)
158 locals.local.add_queue(queue) if(locals.local.respond_to?(:add_queue))
159 return queue
160 end
161 def self.parse(tokens)
162 line = tokens.pos
163 type_name = QualifiedName.parse(tokens)
164 name = tokens.expect(:tWord).data
165 tokens.expect(:tSemi)
166 return self.new(type_name,name).set_line(line)
167 end
168end