blob: 1199cc22d1ccecd70ef6cdf582550221361ef1a8 [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
brians343bc112013-02-10 01:53:46 +00006 @name = name
7 @length = length
8 end
9 CommonMistakes = {"short" => "int16_t","int" => "int32_t","long" => "int64_t"}
Parker Schuh343481e2014-02-09 18:28:43 -080010 def check_type_error(locals)
brians343bc112013-02-10 01:53:46 +000011 if(!(Sizes[@type] || (@length != nil && @type == "char")) )
12 if(correction = CommonMistakes[@type])
13 raise QError.new(<<ERROR_MSG)
14Hey! you have a \"#{@type}\" in your message statement.
15\tplease use #{correction} instead. Your type is not supported because we
16\twant to guarantee that the sizes of the messages stay the same across platforms.
17\tWot. Wot.
18ERROR_MSG
19 elsif(@type == "char")
20 raise QError.new(<<ERROR_MSG)
21Hey! you have a \"#{@type}\" in your message statement.
22\tyou need your declaration to be a char array like: char[10].
23\tor, please use int8_t or uint8_t.
24\tWot. Wot.
25ERROR_MSG
26 else
Parker Schuh343481e2014-02-09 18:28:43 -080027 @is_struct_type = true
28 return if(lookup_type(locals))
brians343bc112013-02-10 01:53:46 +000029 raise QError.new(<<ERROR_MSG)
30Hey! you have a \"#{@type}\" in your message statement.
31\tThat is not in the list of supported types.
32\there is the list of supported types:
Parker Schuh343481e2014-02-09 18:28:43 -080033\tint{8,16,32,64}_t,uint{8,16,32,64}_t,bool,float,double
brians343bc112013-02-10 01:53:46 +000034\tWot. Wot.
35ERROR_MSG
36 end
37 end
38 end
39
40 PrintFormat = {"bool" => "%c",
41 "float" => "%f",
42 "char" => "%c",
43 "double" => "%f",
Brian Silverman8efe23e2013-07-07 23:31:37 -070044 "uint8_t" => "%\" PRIu8 \"",
45 "uint16_t" => "%\" PRIu16 \"",
46 "uint32_t" => "%\" PRIu32 \"",
47 "uint64_t" => "%\" PRIu64 \"",
48 "int8_t" => "%\" PRId8 \"",
49 "int16_t" => "%\" PRId16 \"",
50 "int32_t" => "%\" PRId32 \"",
51 "int64_t" => "%\" PRId64 \""}
brians343bc112013-02-10 01:53:46 +000052 def toPrintFormat()
53 if(format = PrintFormat[@type])
54 return format;
55 end
56 raise QError.new(<<ERROR_MSG)
57Somehow this slipped past me, but
58\tI couldn't find the print format of #{@type}. Really, my bad.
59\tWot. Wot.
60ERROR_MSG
61 end
62
63 Sizes = {"bool" => 1, "float" => 4,"double" => 8}
64 [8,16,32,64].each do |len|
65 Sizes["int#{len}_t"] = len / 8
66 Sizes["uint#{len}_t"] = len / 8
67 end
68 Zero = {"float" => "0.0f","double" => "0.0","bool" => "false"}
69 def size()
70 if(size = Sizes[@type]); return size; end
71 return 1 if(@type == "char")
72 raise QError.new(<<ERROR_MSG)
73Somehow this slipped past me, but
74\tI couldn't find the size of #{@type}. Really, my bad.
75\tWot. Wot.
76ERROR_MSG
77 end
Parker Schuh343481e2014-02-09 18:28:43 -080078 def lookup_type(locals)
79 return @type_name.lookup(locals)
80 end
brians343bc112013-02-10 01:53:46 +000081 def q_eval(locals)
Parker Schuh343481e2014-02-09 18:28:43 -080082 check_type_error(locals)
83 if(@is_struct_type)
84 tval = lookup_type(locals)
85 member = Target::MessageStructElement.new(tval, name)
brians343bc112013-02-10 01:53:46 +000086 else
Parker Schuh343481e2014-02-09 18:28:43 -080087 if(@length == nil)
88 member = Target::MessageElement.new(@type,@name)
89 else
90 member = Target::MessageArrayElement.new(@type,@name,@length)
91 end
92 member.size = size()
93 member.zero = Zero[@type] || "0";
94 member.printformat = toPrintFormat()
brians343bc112013-02-10 01:53:46 +000095 end
brians343bc112013-02-10 01:53:46 +000096 locals.local.add_member(member)
97 end
98 def self.parse(tokens)
99 line = tokens.pos
Parker Schuh343481e2014-02-09 18:28:43 -0800100 #type = tokens.expect(:tWord).data
101 type_name = QualifiedName.parse(tokens)
brians343bc112013-02-10 01:53:46 +0000102 len = nil
103 if(tokens.peak == :tOpenB)
104 tokens.expect(:tOpenB)
105 len = tokens.expect(:tNumber).data
106 tokens.expect(:tCloseB)
107 end
108 name = tokens.expect(:tWord).data
109 tokens.expect(:tSemi)
Parker Schuh343481e2014-02-09 18:28:43 -0800110 return self.new(type_name,name,len).set_line(line)
brians343bc112013-02-10 01:53:46 +0000111 end
112end
113class MessageStmt < QStmt
114 def initialize(name,suite)
115 @name = name
116 @suite = suite
117 end
118 def q_eval(locals)
119 group = Target::MessageDec.new(@name)
120 locals.register(group)
121 @suite.each do |stmt|
122 stmt.q_eval(locals.bind(group))
123 end
124 return group
125 end
126 def self.parse(tokens)
127 name = tokens.expect(:tWord).data
128 values = []
129 tokens.expect(:tOpenB)
130 while(tokens.peak != :tCloseB)
131 values << MessageElementStmt.parse(tokens)
132 end
133 names = {}
134 values.each do |val|
135 if(names[val.name])
136 raise QSyntaxError.new(<<ERROR_MSG)
137Hey! duplicate name #{val.name.inspect} in your message declaration statement (message #{name}).
138\tI found them at: #{names[val.name].q_stack_name()} and #{val.q_stack_name()}.
139\tWot. Wot.
140ERROR_MSG
141 end
142 names[val.name] = val
143 end
144 tokens.expect(:tCloseB)
145 tokens.expect(:tSemi)
146 self.new(name,values)
147 end
148end
149class QueueStmt < QStmt
150 def initialize(type,name)
151 @type,@name = type,name
152 end
153 def q_eval(locals)
154 queue = Target::QueueDec.new(@type.lookup(locals),@name)
155 locals.register(queue)
156 locals.local.add_queue(queue) if(locals.local.respond_to?(:add_queue))
157 return queue
158 end
159 def self.parse(tokens)
160 line = tokens.pos
161 type_name = QualifiedName.parse(tokens)
162 name = tokens.expect(:tWord).data
163 tokens.expect(:tSemi)
164 return self.new(type_name,name).set_line(line)
165 end
166end