source: azure_iot_hub/trunk/asp3_dcre/tecsgen/tecslib/core/expression.rb@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 41.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2017 by TOPPERS Project
7#--
8# 上記著作権者
9は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11# 変・再é…
12å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
13# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15# スコード中に含まれていること.
16# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17# 用できる形で再é…
18å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
19å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
20# 者
21マニュアルなど)に,上記の著作権表示,この利用条件および下記
22# の無保証規定を掲載すること.
23# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24# 用できない形で再é…
25å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
26# と.
27# (a) 再é…
28å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
29マニュアルなど)に,上記の著
30# 作権表示,この利用条件および下記の無保証規定を掲載すること.
31# (b) 再é…
32å¸ƒã®å½¢æ…
33‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
34# 報告すること.
35# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36# 害からも,上記著作権者
37およびTOPPERSプロジェクトをå…
38è²¬ã™ã‚‹ã“と.
39# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
40# 由に基づく請求からも,上記著作権者
41およびTOPPERSプロジェクトを
42# å…
43è²¬ã™ã‚‹ã“と.
44#
45# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
46お
47# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
48# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
49# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
50# の責任を負わない.
51#
52# $Id$
53#++
54
55class Expression < Node
56# @elements # array
57
58 def initialize( elements, locale = nil )
59 super()
60 if locale then
61 @locale = locale
62 end
63
64 @elements = elements
65 end
66
67 def print
68 # puts "expr: #{@elements}"
69 puts "expr_string: #{to_s}"
70 end
71
72 #=== Expression# to_s
73 # C 言語ソース向きの文字列を生成 (globa_name)
74 def to_s
75 elements_to_s( @elements )
76 end
77
78 #=== Expression# to_str
79 # C 言語ソース向きの文字列を生成 (globa_name)
80 def to_str( name_list, pre, post )
81 elements_to_s( @elements, name_list, pre, post )
82 end
83
84 #=== Expression#to_CDL_str
85 # CDL 表現の文字列を生成
86 def to_CDL_str
87 return to_s
88 end
89
90 #=== 定数式として評価する(トライしてみる)
91 #
92 # このメソッドは、定数式を評価する
93 # ・attribute, var の初期化子
94 # ・size_is, count_is 引数
95 # ・é…
96åˆ—の添数
97 #
98 # name_list(NamedList|Nil): 式から参ç…
99§å¯èƒ½ãªãƒªã‚¹ãƒˆï¼Ž
100 # NamedList の要素は size_is, count_is の引数評価の場合 ParamDecl (関数仮引数)
101 #
102 # name_list2(NamedList|Nil) : NamedList の要素は Decl (attribute, var) である.省略時 nil
103 #
104 # RETURN: 評価した定数.評価できなかった場合は nil を返す
105 #
106 # 型は get_type で、評価する(定数として求められないときに使用できる)
107 # Array を返すのは attr{ int *a = {1, 2, 3}; int *b = a; }; の b の右辺を評価した場合
108
109 def eval_const( name_list, name_list2 = nil )
110 val = elements_eval_const( @elements, name_list, name_list2, 0 )
111 if val.kind_of? IntegerVal then
112 return val.to_i
113 elsif val.kind_of? FloatVal then
114 return val.to_f
115 elsif val.kind_of? BoolVal then
116 return val.to_i
117 elsif val.kind_of? PointerVal then
118 return val.to_i # mikan エラー V1008 が発生してしまう
119 # elsif val.kind_of? EnumVal then
120 # enum mikan
121 else
122 # C_EXP, Array または nil :そのまま返す
123 return val
124 end
125 end
126
127 #=== 定数式として評価する2(トライしてみる)
128 #
129 # IntegerVal, FloatVal をそのまま返す(eval_const では Integer, Float に変換)
130 def eval_const2( name_list, name_list2 = nil, nest = 0 )
131 val = elements_eval_const( @elements, name_list, name_list2, nest )
132 end
133
134 #=== 式の型を評価する
135 #
136 # eval_const で値が得られない場合、型を導出可能であれば型を得る
137 # param を含んだ式は定数値を求められないが、型を得ることはできる
138 # 未定義変数を含んだ型は、得ることができない (ダミー型定義が返る)
139 def get_type( namedList ) # 名前空間の NamedList を指定
140 elements_get_type( @elements, namedList )
141 end
142
143 def check_dir_for_param( namedList, dir, spec )
144 elements_check_dir_for_param( @elements, namedList, dir, spec )
145 end
146
147 def get_elements
148 @elements
149 end
150
151 def show_tree( indent )
152 # mikan override してしまった print を呼出す方法がわからないのでこうした
153 str = ""
154 indent.times { str += " " }
155 puts "#{str}#{to_s}"
156 end
157
158## private
159
160 #=== 式を文字列に変換
161 #name_list:: attribute (Celltype::@attribute_list), struct の @member_list を仮定している
162 def elements_to_s( elements, name_list = nil, pre = nil, post = nil )
163 if elements.instance_of? Token then
164 return elements.to_s # OP_DOT, OP_REF の右辺
165 end
166
167 case elements[0]
168 when :IDENTIFIER
169 nsp = elements[1]
170 # if nsp.is_name_only? && name_list && name_list.get_item( nsp.get_name ) then
171 if nsp.is_name_only? && name_list && name_list.get_item( nsp.get_name ) then
172 return "#{pre}#{nsp.get_name}#{post}"
173 else
174 # return elements[1].get_global_name
175 return nsp.get_path_str
176 end
177 when :INTEGER_CONSTANT, :FLOATING_CONSTANT, :OCTAL_CONSTANT, :HEX_CONSTANT, :CHARACTER_LITERAL, :STRING_LITERAL_LIST, :BOOL_CONSTANT
178 return elements[1].to_s
179 when :PARENTHESES
180 return "(#{elements_to_s(elements[1],name_list,pre,post)})"
181 when :OP_SUBSC
182 return "#{elements_to_s(elements[1],name_list,pre,post)}[#{elements[2].to_s}]"
183 when :OP_DOT
184 return "#{elements_to_s(elements[1],name_list,pre,post)}.#{elements_to_s(elements[2],name_list,pre,post)}"
185 when :OP_REF
186 return "#{elements_to_s(elements[1],name_list,pre,post)}->#{elements_to_s(elements[2],name_list,pre,post)}"
187 when :OP_SIZEOF_EXPR
188 return "sizeof(#{elements_to_s(elements[1],name_list,pre,post)})"
189 when :OP_SIZEOF_TYPE
190 return "sizeof(#{elements[1]}) mikan"
191 when :OP_U_AMP
192 return "&#{elements_to_s(elements[1],name_list,pre,post)}"
193 when :OP_U_ASTER
194 return "*#{elements_to_s(elements[1],name_list,pre,post)}"
195 when :OP_U_PLUS
196 return "+#{elements_to_s(elements[1],name_list,pre,post)}"
197 when :OP_U_MINUS
198 return "-#{elements_to_s(elements[1],name_list,pre,post)}"
199 when :OP_U_TILDE
200 return "~#{elements_to_s(elements[1],name_list,pre,post)}"
201 when :OP_U_EXCLAM
202 return "!#{elements_to_s(elements[1],name_list,pre,post)}"
203 when :CAST
204 return "(#{elements[1].get_type_str})#{elements_to_s(elements[2],name_list,pre,post)}"
205 when :OP_MULT
206 return "#{elements_to_s(elements[1],name_list,pre,post)}*#{elements_to_s(elements[2],name_list,pre,post)}"
207 when :OP_DIV
208 return "#{elements_to_s(elements[1],name_list,pre,post)}/#{elements_to_s(elements[2],name_list,pre,post)}"
209 when :OP_REMAIN
210 return "#{elements_to_s(elements[1],name_list,pre,post)}%#{elements_to_s(elements[2],name_list,pre,post)}"
211 when :OP_ADD
212 return "#{elements_to_s(elements[1],name_list,pre,post)}+#{elements_to_s(elements[2],name_list,pre,post)}"
213 when :OP_SUB
214 return "#{elements_to_s(elements[1],name_list,pre,post)}-#{elements_to_s(elements[2],name_list,pre,post)}"
215 when :OP_LSFT
216 return "#{elements_to_s(elements[1],name_list,pre,post)}<<#{elements_to_s(elements[2],name_list,pre,post)}"
217 when :OP_RSFT
218 return "#{elements_to_s(elements[1],name_list,pre,post)}>>#{elements_to_s(elements[2],name_list,pre,post)}"
219 when :OP_LT
220 return "#{elements_to_s(elements[1],name_list,pre,post)}<#{elements_to_s(elements[2],name_list,pre,post)}"
221 when :OP_GT
222 return "#{elements_to_s(elements[1],name_list,pre,post)}>#{elements_to_s(elements[2],name_list,pre,post)}"
223 when :OP_LE
224 return "#{elements_to_s(elements[1],name_list,pre,post)}<=#{elements_to_s(elements[2],name_list,pre,post)}"
225 when :OP_GE
226 return "#{elements_to_s(elements[1],name_list,pre,post)}>=#{elements_to_s(elements[2],name_list,pre,post)}"
227 when :OP_EQ
228 return "#{elements_to_s(elements[1],name_list,pre,post)}==#{elements_to_s(elements[2],name_list,pre,post)}"
229 when :OP_NE
230 return "#{elements_to_s(elements[1],name_list,pre,post)}!=#{elements_to_s(elements[2],name_list,pre,post)}"
231 when :OP_AND
232 return "#{elements_to_s(elements[1],name_list,pre,post)}&#{elements_to_s(elements[2],name_list,pre,post)}"
233 when :OP_EOR
234 return "#{elements_to_s(elements[1],name_list,pre,post)}^#{elements_to_s(elements[2],name_list,pre,post)}"
235 when :OP_OR
236 return "#{elements_to_s(elements[1],name_list,pre,post)}|#{elements_to_s(elements[2],name_list,pre,post)}"
237 when :OP_LAND
238 return "#{elements_to_s(elements[1],name_list,pre,post)}&&#{elements_to_s(elements[2],name_list,pre,post)}"
239 when :OP_LOR
240 return "#{elements_to_s(elements[1],name_list,pre,post)}||#{elements_to_s(elements[2],name_list,pre,post)}"
241 when :OP_CEX
242 return "#{elements_to_s(elements[1],name_list,pre,post)}?#{elements_to_s(elements[2],name_list,pre,post)}:#{elements_to_s(elements[3],name_list,pre,post)}"
243 else
244 raise "Unknown expression element: #{elemets[0]}. try -t and please report"
245 end
246 return ""
247 end
248
249 #=== Expression# 逆ポーランド文字列化
250 #param_list:: ParamlList 関数の引数リスト
251 def get_rpn( param_list = nil, name_list2 = nil )
252 return elements_rpn( @elements, param_list, name_list2 )
253 end
254
255 #=== Expression# 逆ポーランド文字列化 (private)
256 #name_list:: ParamlList 関数の引数リスト
257 def elements_rpn( elements, name_list = nil, name_list2 = nil )
258 if elements.instance_of? Token then
259 print "rpn: #{elements.to_s}\n"
260 return elements.to_s # OP_DOT, OP_REF の右辺
261 end
262
263 case elements[0]
264 when :IDENTIFIER
265 nsp = elements[1]
266 #if nsp.is_name_only? && name_list && name_list.find( nsp.get_name ) then
267 if nsp.is_name_only? then
268 count = 0
269 # p "search: #{nsp.get_name}"
270 name_list.get_items.each{ |nm,val|
271 # p " : #{nm.get_name} #{nsp.get_name.class} #{nm.get_name.class}"
272 if nsp.get_name == nm.get_name then
273 return " $#{count}"
274 end
275 count += 1
276 }
277 raise "not found parameter"
278 else
279 # return elements[1].get_global_name
280 raise "not unexpected parameter"
281 end
282 when :INTEGER_CONSTANT, :FLOATING_CONSTANT, :OCTAL_CONSTANT, :HEX_CONSTANT, :CHARACTER_LITERAL, :STRING_LITERAL_LIST, :BOOL_CONSTANT
283 return elements[1].to_s
284 when :PARENTHESES
285 return elements_rpn( elements[1], name_list, name_list2 )
286 when :OP_SUBSC
287 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[1], "", name_list, name_list2 ) + " []"
288 when :OP_DOT
289 return elements_rpn( elements[1], name_list, name_list2 ) + " ."
290 when :OP_REF
291 return elements_rpn( elements[1], name_list, name_list2 ) + " ->"
292 when :OP_SIZEOF_EXPR
293 return elements_rpn( elements[1], name_list, name_list2 ) + " #s"
294 when :OP_SIZEOF_TYPE
295 return elements_rpn( elements[1], name_list, name_list2 ) + " #S"
296 when :OP_U_AMP
297 return elements_rpn( elements[1], name_list, name_list2 ) + " #&"
298 when :OP_U_ASTER
299 return elements_rpn( elements[1], name_list, name_list2 ) + " #*"
300 when :OP_U_PLUS
301 return elements_rpn( elements[1], name_list, name_list2 ) + " #+"
302 when :OP_U_MINUS
303 return elements_rpn( elements[1], name_list, name_list2 ) + " #-"
304 when :OP_U_TILDE
305 return elements_rpn( elements[1], name_list, name_list2 ) + " #~"
306 when :OP_U_EXCLAM
307 return elements_rpn( elements[1], name_list, name_list2 ) + " #!"
308 when :CAST
309 return elements_rpn( elements[1], name_list, name_list2 ) + " #(" + elements_rpn( elements[2], "", name_list, name_list2 ) + ")"
310 when :OP_MULT
311 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " *"
312 when :OP_DIV
313 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " /"
314 when :OP_REMAIN
315 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " %"
316 when :OP_ADD
317 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " +"
318 when :OP_SUB
319 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " -"
320 when :OP_LSFT
321 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " <<"
322 when :OP_RSFT
323 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " >>"
324 when :OP_LT
325 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " <"
326 when :OP_GT
327 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " >"
328 when :OP_LE
329 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " <="
330 when :OP_GE
331 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " >="
332 when :OP_EQ
333 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " =="
334 when :OP_NE
335 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " !="
336 when :OP_AND
337 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " &"
338 when :OP_EOR
339 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " ^"
340 when :OP_OR
341 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " |"
342 when :OP_LAND
343 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " &&"
344 when :OP_LOR
345 return elements_rpn( elements[1], name_list, name_list2 ) + " " + elements_rpn( elements[2], "", name_list, name_list2 ) + " ||"
346 when :OP_CEX
347 return elements_rpn( elements[1], name_list, name_list2 ) + " " +
348 elements_rpn( elements[2], name_list, name_list2 ) + " " +
349 elements_rpn( elements[3], name_list, name_list2 ) + " ?:"
350 else
351 raise "Unknown expression element: #{elemets[0]}. try -t and please report"
352 end
353 return ""
354 end
355
356 # 定数式(elements)を評価する
357 #
358 # このメソッドは Expression クラスのメソッドである必
359要はない(関数化できる)
360 #
361 # elements は式の要素
362 #
363 # name_list, name_list2 は eval_const を参ç…
364§
365 #
366 # RETURN: 評価した定数、評価できなかった場合は nil を返す
367
368 MAX_NEST_LEVEL = 64 # 簡易のループ検出(参ç…
369§ã®ãƒã‚¹ãƒˆã‚’ 64 まで許可する)
370 def elements_eval_const( elements, name_list, name_list2 = nil, nest = nil )
371
372 case elements[0]
373 when :IDENTIFIER
374 nsp = elements[1]
375
376 # #809 の修正しかけ (別の問題が解決しきれていない)
377 # nest += 1 # 参ç…
378§ãŒãƒ«ãƒ¼ãƒ—になっていないかのチェック
379 # # mikan 本当にループしているかどうかではなく、単純に多数の参ç…
380§ã‚’繰り返していることで判定している
381 # if nest > MAX_NEST_LEVEL then
382 # cdl_error( "E9999: '$1' too many reference (maybe loop) max=$1" , nsp.to_s, MAX_NEST_LEVEL )
383 # return
384 # end
385 if nsp.is_name_only? then
386 if name_list then
387 object = name_list.get_item( nsp.get_name )
388 end
389
390 if object == nil && name_list2 then
391 object = name_list2.get_item( nsp.get_name )
392 end
393 end
394
395 # 見つからなければ定数定義から探す
396 if object == nil then
397 object = Namespace.find( nsp )# mikan namespace の対応 #1
398 end
399
400# この実装
401は、もう少し整理されるべき
402# これが呼出されるのは、以下の場合
403# ・attribute, var の右辺式の評価
404# ・size_is 引数の評価:関数パラメータの場合とattribute, var の場合がある
405# 以下のエラーチェックでは、これらがごっちゃになって誤りを検出しようとしている
406
407 # IDENTIFIER は見つからなかった?
408 if object == nil then
409 cdl_error( "E1001 $1: not found" , nsp.get_path_str )
410 # raise "E1001" # bug trap
411 return nil
412 elsif object.instance_of?( Join ) then
413 # Join の場合: cell の中の attribute, var, call のどれかが見つかった
414 # Decl (attribute, var) でない?
415 if ! object.get_definition.instance_of?( Decl ) then
416 cdl_error( "E1002 $1: not constant (port)" , nsp.get_path_str )
417 return nil
418 end
419 return object.get_rhs.eval_const2( name_list, name_list2, nest )
420 elsif ! object.instance_of?( Decl ) then
421 # Decl でない場合: 定数でもない
422 if ( ! object.instance_of?( ParamDecl ) ) then
423 # mikan paramdecl は無視する
424 # ParamList から呼ばれたとき
425 cdl_error( "E1003 $1: not constant" , nsp.get_path_str )
426 else
427 # ParamDecl
428 object.referenced
429 end
430 return nil
431 else # Decl
432 object.referenced
433 if object.get_initializer == nil then
434 # 初期化子の存在しない変数 # mikan ここへくるのは、通常ありえないはず(未検証)
435 return IntegerVal.new( 0 )
436 else
437 # Decl の右辺の評価
438 # mikan size_is 引数に現れる変数の型が適切かのチェックする
439 if object.get_initializer.instance_of?( Expression ) || object.get_initializer.instance_of?( C_EXP ) then
440 return object.get_initializer.eval_const2( name_list, name_list2, nest )
441 else
442 # Array の場合
443 return object.get_initializer
444 end
445 end
446 end
447 when :BOOL_CONSTANT
448 if( elements[1].instance_of?( TrueClass ) )then
449 return BoolVal.new( true )
450 elsif( elements[1].instance_of?( FalseClass ) )then
451 return BoolVal.new( false )
452 else
453 throw( "BOOL constant error" )
454 end
455 when :INTEGER_CONSTANT
456 return IntegerVal.new( elements[1].val )
457 when :FLOATING_CONSTANT
458 return FloatVal.new( elements[1].val )
459 when :OCTAL_CONSTANT
460 return IntegerVal.new( elements[1].val.oct, elements[1].val )
461 when :HEX_CONSTANT
462 return IntegerVal.new( elements[1].val.hex, elements[1].val )
463 when :CHARACTER_LITERAL
464 str = elements[1].val.gsub(/'/, "" )
465#2.0 if str.jlength == 1
466 if $b_no_kcode then
467 len = str.length
468 else
469 len = str.jlength
470 end
471 if len == 1 then
472 sum = 0
473 str.each_byte { |b| sum = sum * 256 + b }
474 return IntegerVal.new( sum, elements[1].val )
475 else
476#2.0 if str[0] == 92 then
477 if str[0] == 92 || str[0] == "\\" then
478 case str[1]
479#2.0 when 48 # '0'
480 when 48, "0" # '0'
481 return IntegerVal.new( 0, elements[1].val )
482#2.0 when 110 # 'n'
483 when 110, "n" # 'n'
484 return IntegerVal.new( 10, elements[1].val )
485#2.0 when 114 # 'r'
486 when 114, "r" # 'r'
487 return IntegerVal.new( 13, elements[1].val )
488#2.0 when 116 # 't'
489 when 116, "t" # 't'
490 return IntegerVal.new( 15, elements[1].val )
491#2.0 when 92 # '\\'
492 when 92, '\\' # '\\'
493 return IntegerVal.new( 92, elements[1].val )
494 end
495 end
496 end
497#2.0 printf( "c=%c\n", str[1] )
498 printf( "len=%d c=%c\n", len, str[1] )
499 raise Error
500
501 when :STRING_LITERAL_LIST
502 return StringVal.new( elements[1] )
503 when :PARENTHESES
504 return elements_eval_const( elements[1], name_list, name_list2, nest );
505 when :OP_SUBSC
506 cdl_error( "E1004 cannot evaluate \'[]\' operator" )
507 return nil
508 when :OP_DOT
509 cdl_error( "E1005 cannot evaluate \'.\' operator" )
510 return nil
511 when :OP_REF
512 cdl_error( "E1006 cannot evaluate \'->\' operator" )
513 return nil
514 when :OP_SIZEOF_EXPR
515 if Generator.parsing_C? then
516 cdl_info( "I9999 cannot evaluate \'sizeof\' operator. this might causes later error." )
517 else
518 cdl_error( "E1007 cannot evaluate \'sizeof\' operator" )
519 end
520 return nil
521 when :OP_SIZEOF_TYPE
522 if Generator.parsing_C? then
523 cdl_info( "I9999 cannot evaluate \'sizeof\' operator. this might causes later error." )
524 else
525 cdl_error( "E1008 cannot evaluate \'sizeof\' operator" )
526 end
527 return nil
528 when :OP_U_AMP
529 cdl_error( "E1009 cannot evaluate \'&\' operator" )
530 return nil
531 when :OP_U_ASTER
532 # cdl_error( "E1010 cannot evaluate \'*\' operator" )
533 val = elements_eval_const(elements[1], name_list, name_list2, nest)
534 return nil if ! evaluable?( val )
535 return val
536 when :OP_U_PLUS
537 val = elements_eval_const(elements[1], name_list, name_list2, nest)
538 return nil if ! evaluable?( val )
539 if val.respond_to?( "+@" ) then
540 return + val
541 else
542 cdl_error( "E1011 cannot evaluate unary + for $1" , val.class )
543 return nil
544 end
545 when :OP_U_MINUS
546 val = elements_eval_const(elements[1], name_list, name_list2, nest)
547 return nil if ! evaluable?( val )
548 if val.respond_to?( "-@" ) then
549 return - val
550 else
551 return nil
552 end
553 when :OP_U_TILDE
554 val = elements_eval_const(elements[1], name_list, name_list2, nest)
555 return nil if ! evaluable?( val )
556# p "val.respond_to?( \"-@\" )=#{val.respond_to?( "-@" )} #{val.class}"
557# p "val.respond_to?( \"~@\" )=#{val.respond_to?( "~@" )}"
558#2.0 if val.respond_to?( "~@" ) then # Ruby 1.9, 2.0 preview 版では例外が発生してしまう
559 if val.kind_of? IntegerVal then
560 return ~ val
561 else
562 return nil
563 end
564 when :OP_U_EXCLAM
565 val = elements_eval_const(elements[1], name_list, name_list2, nest)
566 return nil if ! evaluable?( val )
567 val = val.cast( BoolType.new )
568 if val.respond_to?( "not" ) then
569 return val.not
570 else
571 return nil
572 end
573 return nil
574 when :CAST
575 val = elements_eval_const(elements[2], name_list, name_list2, nest)
576 # return nil if val == nil
577 return nil if ! evaluable?( val )
578 return val.cast( elements[1] )
579 when :OP_MULT
580 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
581 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
582 # return nil if( rhs == nil || lhs == nil )
583 return nil if ! evaluable?( rhs, lhs )
584 return lhs * rhs
585 when :OP_DIV
586 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
587 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
588 # return nil if( rhs == nil || lhs == nil )
589 return nil if ! evaluable?( rhs, lhs )
590 return lhs / rhs
591 when :OP_REMAIN
592 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
593 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
594 # return nil if( rhs == nil || lhs == nil )
595 return nil if ! evaluable?( rhs, lhs )
596 return lhs % rhs
597 when :OP_ADD
598 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
599 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
600 # return nil if( rhs == nil || lhs == nil )
601 return nil if ! evaluable?( rhs, lhs )
602 return lhs + rhs
603 when :OP_SUB
604 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
605 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
606 # return nil if( rhs == nil || lhs == nil )
607 return nil if ! evaluable?( rhs, lhs )
608 return lhs - rhs
609 when :OP_LSFT
610 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
611 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
612 # return nil if( rhs == nil || lhs == nil )
613 return nil if ! evaluable?( rhs, lhs )
614 return lhs << rhs
615 when :OP_RSFT
616 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
617 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
618 # return nil if( rhs == nil || lhs == nil )
619 return nil if ! evaluable?( rhs, lhs )
620 return lhs >> rhs
621 when :OP_LT
622 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
623 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
624 # return nil if( rhs == nil || lhs == nil )
625 return nil if ! evaluable?( rhs, lhs )
626 return lhs < rhs
627 when :OP_GT
628 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
629 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
630 # return nil if( rhs == nil || lhs == nil )
631 return nil if ! evaluable?( rhs, lhs )
632 return lhs > rhs
633 when :OP_LE
634 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
635 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
636 # return nil if( rhs == nil || lhs == nil )
637 return nil if ! evaluable?( rhs, lhs )
638 return lhs <= rhs
639 when :OP_GE
640 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
641 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
642 # return nil if( rhs == nil || lhs == nil )
643 return nil if ! evaluable?( rhs, lhs )
644 return lhs >= rhs
645 when :OP_EQ
646 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
647 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
648 # return nil if( rhs == nil || lhs == nil )
649 return nil if ! evaluable?( rhs, lhs )
650 return lhs.eq( rhs )
651 when :OP_NE
652 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
653 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
654 # return nil if( rhs == nil || lhs == nil )
655 return nil if ! evaluable?( rhs, lhs )
656 return lhs.neq( rhs )
657 when :OP_AND
658 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
659 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
660 # return nil if( rhs == nil || lhs == nil )
661 return nil if ! evaluable?( rhs, lhs )
662 return lhs & rhs
663 when :OP_EOR
664 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
665 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
666 # return nil if( rhs == nil || lhs == nil )
667 return nil if ! evaluable?( rhs, lhs )
668 return lhs ^ rhs
669 when :OP_OR
670 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
671 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
672 # return nil if( rhs == nil || lhs == nil )
673 return nil if ! evaluable?( rhs, lhs )
674 return lhs | rhs
675 when :OP_LAND
676 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
677 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
678 # return nil if( rhs == nil || lhs == nil )
679 return nil if ! evaluable?( rhs, lhs )
680 return lhs.lAND( rhs )
681 when :OP_LOR
682 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
683 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
684 # return nil if( rhs == nil || lhs == nil )
685 return nil if ! evaluable?( rhs, lhs )
686 return lhs.lOR( rhs )
687 when :OP_CEX
688 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
689 mhs = elements_eval_const(elements[2], name_list, name_list2, nest)
690 rhs = elements_eval_const(elements[3], name_list, name_list2, nest)
691 # return nil if( rhs == nil || mhs == nil || lhs == nil )
692 return nil if ! evaluable?( rhs, mhs, lhs )
693 if lhs.cast( BoolType.new ).val then
694 return mhs
695 else
696 return rhs
697 end
698 end
699 return nil
700 end
701
702 def elements_get_type( elements, namedList )
703 type = elements_get_type_sub( elements, namedList )
704 # 返された方が DefinedType の場合 å…
705ƒã®åž‹ã‚’返す
706 if type.kind_of?( DefinedType ) then
707 type = type.get_type
708 end
709 return type
710 end
711
712 def elements_get_type_sub( elements, namedList )
713 case elements[0]
714 when :IDENTIFIER
715 nsp = elements[1]
716 if nsp.is_name_only? then
717 paramdecl = namedList.get_item( nsp.get_name )
718 else
719 paramdecl = nil
720 end
721 unless paramdecl then
722 cdl_error( "E1012 $1: not found in parameter list" , nsp.get_path_str )
723 return IntType.new(32) # dummy result
724 end
725 return paramdecl.get_type
726# mikan get_type
727# when :INTEGER_CONSTANT
728# when :FLOATING_CONSTANT
729# when :OCTAL_CONSTANT
730# when :HEX_CONSTANT
731# when :CHARACTER_LITERAL
732# when :STRING_LITERAL_LIST
733# when :PARENTHESES
734# when :OP_SUBSC
735# when :OP_DOT
736# when :OP_REF
737# when :OP_SIZEOF_EXPR
738# when :OP_SIZEOF_TYPE
739# when :OP_U_AMP
740 when :OP_U_ASTER
741 type = elements_get_type( elements[1], namedList )
742 unless type.kind_of?( PtrType ) then
743 cdl_error( "E1013 \'*\': operand is not pointer value" )
744 return IntType.new( 8 ) # IntType を返しておく
745 end
746 return type.get_referto
747
748 when :OP_U_PLUS, :OP_U_MINUS
749 # mikan operand が適切な型かチェックしていない
750 return elements_get_type( elements[1], namedList )
751
752 when :OP_ADD, :OP_SUB, :OP_MULT, :OP_DIV, :OP_REMAIN
753 # mikan operand が適切な型かチェックしていない&左辺の型を採用している
754 return elements_get_type( elements[1], namedList )
755
756 when :OP_U_TILDE
757 # mikan operand が整数かチェックしていない
758 return elements_get_type( elements[1], namedList )
759 when :OP_AND, :OP_EOR, :OP_OR, :OP_LSFT, :OP_RSFT
760 # mikan operand が整数かチェックしていない
761 return BoolType.new
762 when :OP_U_EXCLAM
763 # mikan operand が整数かチェックしていない
764 return BoolType.new
765
766 when :OP_LT, :OP_GT, :OP_LE, :OP_GE, :OP_EQ, :OP_NE, :OP_LAND, :OP_LOR, :OP_CEX, :CAST
767 cdl_error( "E1014 $1: elements_get_type: sorry not supported" , elements[0] )
768 end
769
770 return nil
771 end
772
773 # 式が size_is, count_is, string の引数である場合の方向のチェック
774 def elements_check_dir_for_param( elements, namedList, dir, spec )
775 # dir : å…
776ƒã®å¼•æ•°ã®æ–¹å‘
777 # direct: size_is などの引数の変数の方向
778
779 case elements[0]
780 when :IDENTIFIER
781 nsp = elements[1]
782 if nsp.is_name_only? then
783 paramdecl = namedList.get_item( nsp.get_name )
784 else
785 paramdecl = nil
786 end
787
788 return unless paramdecl # if nil already error in element_get_type
789
790 direct = paramdecl.get_direction
791 judge = false
792 case spec
793 when "size_is", "string"
794 case dir
795 when :IN, :OUT, :INOUT, :SEND
796 judge = true if ( direct == :IN || direct == :INOUT )
797 req_direct = "in or inout"
798 when :RECEIVE
799 judge = true if ( direct == :OUT || direct == :INOUT )
800 req_direct = "out or inout"
801 end
802
803 when "count_is"
804 case dir
805 when :IN, :SEND
806 judge = true if ( direct == :IN || direct == :INOUT )
807 req_direct = "in or inout"
808 when :OUT, :RECEIVE # mikan out で count_is のみ指定されている場合 in でなくてはならない
809 judge = true if ( direct == :OUT || direct == :INOUT )
810 req_direct = "out or inout"
811 when :INOUT
812 judge = true if ( direct == :INOUT )
813 req_direct = "inout"
814 end
815 end
816
817 if judge == false then
818 cdl_error( "E1015 \'$1\': direction mismatch for $2, $3 required" , nsp.get_path_str, spec, req_direct )
819 end
820
821 when :INTEGER_CONSTANT, :FLOATING_CONSTANT, :OCTAL_CONSTANT, :HEX_CONSTANT, :CHARACTER_LITERAL, :STRING_LITERAL_LIST
822 return true
823
824 # 単項
825演算子
826 when :OP_U_ASTER, :OP_SIZEOF_EXPR, :OP_SIZEOF_TYPE, :OP_U_PLUS, :OP_U_MINUS, :OP_U_TILDE, :OP_U_EXCLAM, :CAST, :OP_U_AMP, :PARENTHESES,
827 elements_check_dir_for_param( elements[1], namedList, dir, spec )
828
829 # 2項
830演算子
831 when :OP_SUBSC, :OP_DOT, :OP_REF, :OP_MULT, :OP_DIV, :OP_REMAIN, :OP_ADD, :OP_SUB, :OP_LSFT, :OP_RSFT, :OP_LT, :OP_GT, :OP_LE, :OP_GE, :OP_EQ, :OP_NE, :OP_AND, :OP_EOR, :OP_OR, :OP_LAND, :OP_LOR
832 return elements_check_dir_for_param( elements[1], namedList, dir, spec ) && elements_check_dir_for_param( elements[2], namedList, dir, spec )
833
834 # 3項
835演算子
836 when :OP_CEX
837 return elements_check_dir_for_param( elements[1], namedList, dir, spec ) && elements_check_dir_for_param( elements[2], namedList, dir, spec ) && elements_check_dir_for_param( elements[3], namedList, dir, spec )
838
839 else
840 cdl_error( "E1016 $1: elements_check_dir_for_param: sorry not supported" , elements[0] )
841 end
842
843 end
844
845 #Express# get_allocator_rhs_elem
846 #alloc_type::Symbol :NORMAL_ALLOC|:INTERNAL_ALLOC|:RELAY_ALLOC
847 #式がアロケータ指定子の右辺として妥当かチェックし、正しければ分解した値を返す
848 #return:
849 # :NORMAL_ALLOC [ cell_nsp, ep_name ] # rhs = cell_nsp.ep_name ex) Alloc.eAlloc
850 # :INTERNAL_ALLOC [ ep_name ] # rhs = ep_name ex) eAlloc
851 # :RELAY_ALLOC [ cp_name, func_name, param_name ] # rhs = cp_name.func_name.param_name
852 def get_allocator_rhs_elements( alloc_type )
853 ele = @elements
854 case alloc_type
855 when :NORMAL_ALLOC
856 if ele[0] != :OP_DOT || ele[1][0] != :IDENTIFIER then #1
857 cdl_error( "E1017 $1: rhs not \'Cell.ePort\' form" , ele[0].to_s )
858 return nil
859 end
860 cell_nsp = elements[1][1]
861 port_name = elements[2].val
862 return [ cell_nsp, port_name ]
863 when :INTERNAL_ALLOC
864 if( ele[0] == :IDENTIFIER )then
865 if ele[1].is_name_only? then
866 return [ ele[1].get_path[0] ] # mikan a::b
867 else
868 cdl_error( "E1018 $1: namespace cannot be specified", ele[1].to_s )
869 end
870 else
871 cdl_error( "E1019 $1: rhs not in 'allocator_entry_port' form", ele[1].to_s )
872 end
873 when :RELAY_ALLOC
874 if( ele[0] != :OP_DOT ||
875 ele[1][0] != :OP_DOT || ele[1][1][0] != :IDENTIFIER || ! ele[1][1][1].is_name_only? ||
876 ! ele[1][2].instance_of?( Token ) || ! ele[2].instance_of?( Token ) )then #1
877 cdl_error( "E1020 rhs not in 'call_port.func.param' form ($1)" , ele[0].to_s ) # S1086
878 end
879 func_name = ele[1][2]; cp_name = ele[1][1][1].get_name; param_name = ele[2].to_sym
880 return [ cp_name, func_name, param_name ]
881 end
882 return nil
883 end
884
885 #Expression#Expression のクローンを作成する
886 def clone_for_composite
887 cl = self.clone
888 elements = clone_elements @elements
889 cl.set_elements elements
890 return cl
891 end
892
893 #Expression#elements のクローンを作成
894 #elements::Array
895 # このメソッドは、Array のディープコピーを行う
896 def clone_elements elements
897 elements = elements.clone
898 elements.map!{ |ele|
899 if ele.instance_of? Array
900 clone_elements ele
901 else
902 ele
903 end
904 }
905 return elements
906 end
907
908 def set_elements elements
909 @elements = elements
910 end
911
912 #=== Expression#セル結合の式を解析する
913 # Cell.eEntry => [ :OP_DOT, [ :IDENTIFIER, token ], token ]
914 # Cell.eEntry[expression] => [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, token ], token ], expression ]
915 # Return: [ NamespacePath(cell_name), Integer(subscript) or nil, Token(port_name)]
916 def analyze_cell_join_expression
917 # 右辺の Expression の要素を取り出す
918 elements = @elements
919 if elements[0] == :OP_SUBSC then # 右辺:受け口é…
920åˆ—?
921 # elements = [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, token ], token ], expression ]
922 subscript = elements[2].eval_const(nil) # 受け口é…
923åˆ—の添数
924 elements = elements[1] # mikan é…
925åˆ—だった場合
926 else
927 subscript = nil
928 end
929
930 # elements = [ :OP_DOT, [ :IDENTIFIER, token ], token ]
931 if elements[0] != :OP_DOT || elements[1][0] != :IDENTIFIER then #1
932 return nil
933 end
934
935 nsp = elements[1][1] # NamespacePath
936 port_name = elements[2].val
937
938 return [ nsp, subscript, port_name]
939 end
940
941 #=== Expression# セルへの結合の式を生成する
942 #nsp:: NamespacePath
943 #subscript:: Integer
944 #port_name:: Symbol
945 # analyze_cell_join_expression と対になっている
946 def self.create_cell_join_expression( nsp, subscript, port_name, locale = nil )
947 if ! port_name.instance_of?( Symbol ) then
948 raise "port_name: not Symbol"
949 end
950
951 if subscript then
952 elements = [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, nsp ],
953 Token.new( port_name, nil, nil, nil ) ],
954 Expression.create_integer_constant( subscript, @locale ) ]
955 else
956 elements = [ :OP_DOT, [ :IDENTIFIER, nsp ], Token.new( port_name, nil, nil, nil ) ]
957 end
958 return Expression.new( elements, locale )
959 end
960
961 #=== Expression#整数定数の式を生成する
962 #val:: Integer : 値: 整数
963 def self.create_integer_constant( val, locale = nil )
964 if val != Integer( val ) || val < 0 then
965 raise "create_integer_constant: not integer or negative: #{val}"
966 end
967 Expression.new( [ :INTEGER_CONSTANT, Token.new( val, nil, nil, nil ) ], locale )
968 end
969
970 #=== Expression#単一の識別子の式を解析する
971 # Identifier => [ :IDENTIFIER, token ]
972 # Return: NamespacePath(Identifier)
973 def analyze_single_identifier
974 # 右辺の Expression の要素を取り出す
975 elements = @elements
976 if elements[0] == :IDENTIFIER
977 return elements[1]
978 else
979 return nil
980 end
981 end
982
983 #=== Expression#
984 #nsp:: NamespacePath : 参ç…
985§ã™ã‚‹ã‚‚の識別子
986 def self.create_single_identifier( nsp, locale )
987 if ! nsp.instance_of?( NamespacePath ) then
988 raise "create_single_identifier: not NamespacePath: #{nsp.to_s}"
989 end
990 Expression.new( [ :IDENTIFIER, nsp ] )
991 end
992
993 #=== 評価可能かチェックする
994 #*v:: 可変個引数(任意の型)
995 # すべてが BaseVal の子クラス(値)であれば、評価可能と判断する
996 def evaluable?( *v )
997 v.each{ |val|
998 if ! val.kind_of?( BaseVal ) then
999 return false
1000 end
1001 }
1002 return true
1003 end
1004
1005 private :elements_to_s, :elements_eval_const, :elements_get_type
1006
1007end
1008
1009
1010class C_EXP < Node
1011# @c_exp_string : string
1012
1013 #c_exp_string::String
1014 #b_renew::Bool : true なら C_EXP の clone 作成(エスケープ処理等をしない)
1015 def initialize( c_exp_string, b_renew = false )
1016 if b_renew then
1017 @c_exp_string = c_exp_string
1018 else
1019 # 前後の " を取り除く
1020 # str = c_exp_string.to_s.sub( /^\"(.*)\"$/, "\\1" )
1021 str = CDLString.remove_dquote c_exp_string.to_s
1022 @c_exp_string = CDLString.escape str
1023 end
1024 end
1025
1026 #=== composite 用に C_EXP を clone する
1027 #ct_name::
1028 #cell_name::
1029 # composite の attribute に現れる C_EXP を文字列置換して生成しなおす.
1030 # この文字列置換は、意味解釈段階で行う.
1031 # 他の C_EXP の文字列置換は、コード生成段階で行う.
1032 def clone_for_composite( ct_name, cell_name, locale )
1033 dbgPrint "C_EXP: #{ct_name} #{cell_name} #{@c_exp_string}\n"
1034
1035 @locale = locale
1036 str = @c_exp_string.gsub( /(^|[^\$])\$ct\$/, "\\1#{ct_name}" )
1037 str = str. gsub( /(^|[^\$])\$cell\$/, "\\1#{cell_name}" )
1038 str = str. gsub( /(^|[^\$])\$id\$/, "\\1#{ct_name}_#{cell_name}" )
1039 return C_EXP.new( str, true )
1040 end
1041
1042 def get_c_exp_string
1043 @c_exp_string
1044 end
1045
1046 #=== C_EXP を評価する
1047 # C_EXP の引き数文字列を返す
1048 # 本来 C_EXP は eval_const する対象ではないが、便宜上 eval_const で対応
1049 def eval_const( name_list, name_list2 = nil )
1050 return self
1051 end
1052 def eval_const2( name_list, name_list2 = nil, nest = nil )
1053 return self
1054 end
1055
1056 def to_s
1057 @c_exp_string
1058 end
1059
1060 def to_CDL_str
1061 return "C_EXP( \"#{to_s}\" )"
1062 end
1063
1064 def show_tree( indent )
1065 indent.times { print " " }
1066 puts "C_EXP: #{@c_exp_string}"
1067 end
1068end
1069
Note: See TracBrowser for help on using the repository browser.