source: asp3_gr_sakura/trunk/tecsgen/tecslib/core/expression.rb@ 317

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

GR-SAKURA向けASP3を追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 35.5 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2014 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: expression.rb 2061 2014-05-31 22:15:33Z okuma-top $
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 return "#{pre}#{nsp.get_name}#{post}"
172 else
173 # return elements[1].get_global_name
174 return nsp.get_path_str
175 end
176 when :INTEGER_CONSTANT, :FLOATING_CONSTANT, :OCTAL_CONSTANT, :HEX_CONSTANT, :CHARACTER_LITERAL, :STRING_LITERAL_LIST, :BOOL_CONSTANT
177 return elements[1].to_s
178 when :PARENTHESES
179 return "(#{elements_to_s(elements[1],name_list,pre,post)})"
180 when :OP_SUBSC
181 return "#{elements_to_s(elements[1],name_list,pre,post)}[#{elements[2].to_s}]"
182 when :OP_DOT
183 return "#{elements_to_s(elements[1],name_list,pre,post)}.#{elements_to_s(elements[2],name_list,pre,post)}"
184 when :OP_REF
185 return "#{elements_to_s(elements[1],name_list,pre,post)}->#{elements_to_s(elements[2],name_list,pre,post)}"
186 when :OP_SIZEOF_EXPR
187 return "sizeof(#{elements_to_s(elements[1],name_list,pre,post)})"
188 when :OP_SIZEOF_TYPE
189 return "sizeof(#{elements[1]}) mikan"
190 when :OP_U_AMP
191 return "&#{elements_to_s(elements[1],name_list,pre,post)}"
192 when :OP_U_ASTER
193 return "*#{elements_to_s(elements[1],name_list,pre,post)}"
194 when :OP_U_PLUS
195 return "+#{elements_to_s(elements[1],name_list,pre,post)}"
196 when :OP_U_MINUS
197 return "-#{elements_to_s(elements[1],name_list,pre,post)}"
198 when :OP_U_TILDE
199 return "~#{elements_to_s(elements[1],name_list,pre,post)}"
200 when :OP_U_EXCLAM
201 return "!#{elements_to_s(elements[1],name_list,pre,post)}"
202 when :CAST
203 return "(#{elements[1].get_type_str})#{elements_to_s(elements[2],name_list,pre,post)}"
204 when :OP_MULT
205 return "#{elements_to_s(elements[1],name_list,pre,post)}*#{elements_to_s(elements[2],name_list,pre,post)}"
206 when :OP_DIV
207 return "#{elements_to_s(elements[1],name_list,pre,post)}/#{elements_to_s(elements[2],name_list,pre,post)}"
208 when :OP_REMAIN
209 return "#{elements_to_s(elements[1],name_list,pre,post)}%#{elements_to_s(elements[2],name_list,pre,post)}"
210 when :OP_ADD
211 return "#{elements_to_s(elements[1],name_list,pre,post)}+#{elements_to_s(elements[2],name_list,pre,post)}"
212 when :OP_SUB
213 return "#{elements_to_s(elements[1],name_list,pre,post)}-#{elements_to_s(elements[2],name_list,pre,post)}"
214 when :OP_LSFT
215 return "#{elements_to_s(elements[1],name_list,pre,post)}<<#{elements_to_s(elements[2],name_list,pre,post)}"
216 when :OP_RSFT
217 return "#{elements_to_s(elements[1],name_list,pre,post)}>>#{elements_to_s(elements[2],name_list,pre,post)}"
218 when :OP_LT
219 return "#{elements_to_s(elements[1],name_list,pre,post)}<#{elements_to_s(elements[2],name_list,pre,post)}"
220 when :OP_GT
221 return "#{elements_to_s(elements[1],name_list,pre,post)}>#{elements_to_s(elements[2],name_list,pre,post)}"
222 when :OP_LE
223 return "#{elements_to_s(elements[1],name_list,pre,post)}<=#{elements_to_s(elements[2],name_list,pre,post)}"
224 when :OP_GE
225 return "#{elements_to_s(elements[1],name_list,pre,post)}>=#{elements_to_s(elements[2],name_list,pre,post)}"
226 when :OP_EQ
227 return "#{elements_to_s(elements[1],name_list,pre,post)}==#{elements_to_s(elements[2],name_list,pre,post)}"
228 when :OP_NE
229 return "#{elements_to_s(elements[1],name_list,pre,post)}!=#{elements_to_s(elements[2],name_list,pre,post)}"
230 when :OP_AND
231 return "#{elements_to_s(elements[1],name_list,pre,post)}&#{elements_to_s(elements[2],name_list,pre,post)}"
232 when :OP_EOR
233 return "#{elements_to_s(elements[1],name_list,pre,post)}^#{elements_to_s(elements[2],name_list,pre,post)}"
234 when :OP_OR
235 return "#{elements_to_s(elements[1],name_list,pre,post)}|#{elements_to_s(elements[2],name_list,pre,post)}"
236 when :OP_LAND
237 return "#{elements_to_s(elements[1],name_list,pre,post)}&&#{elements_to_s(elements[2],name_list,pre,post)}"
238 when :OP_LOR
239 return "#{elements_to_s(elements[1],name_list,pre,post)}||#{elements_to_s(elements[2],name_list,pre,post)}"
240 when :OP_CEX
241 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)}"
242 else
243 raise "Unknown expression element: #{elemets[0]}. try -t and please report"
244 end
245 return ""
246 end
247
248 # 定数式(elements)を評価する
249 #
250 # このメソッドは Expression クラスのメソッドである必
251要はない(関数化できる)
252 #
253 # elements は式の要素
254 #
255 # name_list, name_list2 は eval_const を参ç…
256§
257 #
258 # RETURN: 評価した定数、評価できなかった場合は nil を返す
259
260 MAX_NEST_LEVEL = 64 # 簡易のループ検出(参ç…
261§ã®ãƒã‚¹ãƒˆã‚’ 64 まで許可する)
262 def elements_eval_const( elements, name_list, name_list2 = nil, nest = nil )
263
264 case elements[0]
265 when :IDENTIFIER
266 nsp = elements[1]
267
268 # #809 の修正しかけ (別の問題が解決しきれていない)
269 # nest += 1 # 参ç…
270§ãŒãƒ«ãƒ¼ãƒ—になっていないかのチェック
271 # # mikan 本当にループしているかどうかではなく、単純に多数の参ç…
272§ã‚’繰り返していることで判定している
273 # if nest > MAX_NEST_LEVEL then
274 # cdl_error( "E9999: '$1' too many reference (maybe loop) max=$1" , nsp.to_s, MAX_NEST_LEVEL )
275 # return
276 # end
277 if nsp.is_name_only? then
278 if name_list then
279 object = name_list.get_item( nsp.get_name )
280 end
281
282 if object == nil && name_list2 then
283 object = name_list2.get_item( nsp.get_name )
284 end
285 end
286
287 # 見つからなければ定数定義から探す
288 if object == nil then
289 object = Namespace.find( nsp )# mikan namespace の対応 #1
290 end
291
292# この実装
293は、もう少し整理されるべき
294# これが呼出されるのは、以下の場合
295# ・attribute, var の右辺式の評価
296# ・size_is 引数の評価:関数パラメータの場合とattribute, var の場合がある
297# 以下のエラーチェックでは、これらがごっちゃになって誤りを検出しようとしている
298
299 # IDENTIFIER は見つからなかった?
300 if object == nil then
301 cdl_error( "E1001 $1: not found" , nsp.get_path_str )
302 # raise "E1001" # bug trap
303 return nil
304 elsif object.instance_of?( Join ) then
305 # Join の場合: cell の中の attribute, var, call のどれかが見つかった
306 # Decl (attribute, var) でない?
307 if ! object.get_definition.instance_of?( Decl ) then
308 cdl_error( "E1002 $1: not constant (port)" , nsp.get_path_str )
309 return nil
310 end
311 return object.get_rhs.eval_const2( name_list, name_list2, nest )
312 elsif ! object.instance_of?( Decl ) then
313 # Decl でない場合: 定数でもない
314 if ( ! object.instance_of?( ParamDecl ) ) then
315 # mikan paramdecl は無視する
316 # ParamList から呼ばれたとき
317 cdl_error( "E1003 $1: not constant" , nsp.get_path_str )
318 else
319 # ParamDecl
320 object.referenced
321 end
322 return nil
323 else # Decl
324 object.referenced
325 if object.get_initializer == nil then
326 # 初期化子の存在しない変数 # mikan ここへくるのは、通常ありえないはず(未検証)
327 return IntegerVal.new( 0 )
328 else
329 # Decl の右辺の評価
330 # mikan size_is 引数に現れる変数の型が適切かのチェックする
331 if object.get_initializer.instance_of?( Expression ) || object.get_initializer.instance_of?( C_EXP ) then
332 return object.get_initializer.eval_const2( name_list, name_list2, nest )
333 else
334 # Array の場合
335 return object.get_initializer
336 end
337 end
338 end
339 when :BOOL_CONSTANT
340 if( elements[1].instance_of?( TrueClass ) )then
341 return BoolVal.new( true )
342 elsif( elements[1].instance_of?( FalseClass ) )then
343 return BoolVal.new( false )
344 else
345 throw( "BOOL constant error" )
346 end
347 when :INTEGER_CONSTANT
348 return IntegerVal.new( elements[1].val )
349 when :FLOATING_CONSTANT
350 return FloatVal.new( elements[1].val )
351 when :OCTAL_CONSTANT
352 return IntegerVal.new( elements[1].val.oct, elements[1].val )
353 when :HEX_CONSTANT
354 return IntegerVal.new( elements[1].val.hex, elements[1].val )
355 when :CHARACTER_LITERAL
356 str = elements[1].val.gsub(/'/, "" )
357#2.0 if str.jlength == 1
358 if $b_no_kcode then
359 len = str.length
360 else
361 len = str.jlength
362 end
363 if len == 1 then
364 sum = 0
365 str.each_byte { |b| sum = sum * 256 + b }
366 return IntegerVal.new( sum, elements[1].val )
367 else
368#2.0 if str[0] == 92 then
369 if str[0] == 92 || str[0] == "\\" then
370 case str[1]
371#2.0 when 48 # '0'
372 when 48, "0" # '0'
373 return IntegerVal.new( 0, elements[1].val )
374#2.0 when 110 # 'n'
375 when 110, "n" # 'n'
376 return IntegerVal.new( 10, elements[1].val )
377#2.0 when 114 # 'r'
378 when 114, "r" # 'r'
379 return IntegerVal.new( 13, elements[1].val )
380#2.0 when 116 # 't'
381 when 116, "t" # 't'
382 return IntegerVal.new( 15, elements[1].val )
383#2.0 when 92 # '\\'
384 when 92, '\\' # '\\'
385 return IntegerVal.new( 92, elements[1].val )
386 end
387 end
388 end
389#2.0 printf( "c=%c\n", str[1] )
390 printf( "len=%d c=%c\n", len, str[1] )
391 raise Error
392
393 when :STRING_LITERAL_LIST
394 return StringVal.new( elements[1] )
395 when :PARENTHESES
396 return elements_eval_const( elements[1], name_list, name_list2, nest );
397 when :OP_SUBSC
398 cdl_error( "E1004 cannot evaluate \'[]\' operator" )
399 return nil
400 when :OP_DOT
401 cdl_error( "E1005 cannot evaluate \'.\' operator" )
402 return nil
403 when :OP_REF
404 cdl_error( "E1006 cannot evaluate \'->\' operator" )
405 return nil
406 when :OP_SIZEOF_EXPR
407 cdl_error( "E1007 cannot evaluate \'sizeof\' operator" )
408 return nil
409 when :OP_SIZEOF_TYPE
410 cdl_error( "E1008 cannot evaluate \'sizeof\' operator" )
411 return nil
412 when :OP_U_AMP
413 cdl_error( "E1009 cannot evaluate \'&\' operator" )
414 return nil
415 when :OP_U_ASTER
416 # cdl_error( "E1010 cannot evaluate \'*\' operator" )
417 val = elements_eval_const(elements[1], name_list, name_list2, nest)
418 return nil if ! evaluable?( val )
419 return val
420 when :OP_U_PLUS
421 val = elements_eval_const(elements[1], name_list, name_list2, nest)
422 return nil if ! evaluable?( val )
423 if val.respond_to?( "+@" ) then
424 return + val
425 else
426 cdl_error( "E1011 cannot evaluate unary + for $1" , val.class )
427 return nil
428 end
429 when :OP_U_MINUS
430 val = elements_eval_const(elements[1], name_list, name_list2, nest)
431 return nil if ! evaluable?( val )
432 if val.respond_to?( "-@" ) then
433 return - val
434 else
435 return nil
436 end
437 when :OP_U_TILDE
438 val = elements_eval_const(elements[1], name_list, name_list2, nest)
439 return nil if ! evaluable?( val )
440# p "val.respond_to?( \"-@\" )=#{val.respond_to?( "-@" )} #{val.class}"
441# p "val.respond_to?( \"~@\" )=#{val.respond_to?( "~@" )}"
442#2.0 if val.respond_to?( "~@" ) then # Ruby 1.9, 2.0 preview 版では例外が発生してしまう
443 if val.kind_of? IntegerVal then
444 return ~ val
445 else
446 return nil
447 end
448 when :OP_U_EXCLAM
449 val = elements_eval_const(elements[1], name_list, name_list2, nest)
450 return nil if ! evaluable?( val )
451 val = val.cast( BoolType.new )
452 if val.respond_to?( "not" ) then
453 return val.not
454 else
455 return nil
456 end
457 return nil
458 when :CAST
459 val = elements_eval_const(elements[2], name_list, name_list2, nest)
460 # return nil if val == nil
461 return nil if ! evaluable?( val )
462 return val.cast( elements[1] )
463 when :OP_MULT
464 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
465 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
466 # return nil if( rhs == nil || lhs == nil )
467 return nil if ! evaluable?( rhs, lhs )
468 return lhs * rhs
469 when :OP_DIV
470 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
471 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
472 # return nil if( rhs == nil || lhs == nil )
473 return nil if ! evaluable?( rhs, lhs )
474 return lhs / rhs
475 when :OP_REMAIN
476 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
477 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
478 # return nil if( rhs == nil || lhs == nil )
479 return nil if ! evaluable?( rhs, lhs )
480 return lhs % rhs
481 when :OP_ADD
482 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
483 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
484 # return nil if( rhs == nil || lhs == nil )
485 return nil if ! evaluable?( rhs, lhs )
486 return lhs + rhs
487 when :OP_SUB
488 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
489 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
490 # return nil if( rhs == nil || lhs == nil )
491 return nil if ! evaluable?( rhs, lhs )
492 return lhs - rhs
493 when :OP_LSFT
494 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
495 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
496 # return nil if( rhs == nil || lhs == nil )
497 return nil if ! evaluable?( rhs, lhs )
498 return lhs << rhs
499 when :OP_RSFT
500 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
501 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
502 # return nil if( rhs == nil || lhs == nil )
503 return nil if ! evaluable?( rhs, lhs )
504 return lhs >> rhs
505 when :OP_LT
506 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
507 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
508 # return nil if( rhs == nil || lhs == nil )
509 return nil if ! evaluable?( rhs, lhs )
510 return lhs < rhs
511 when :OP_GT
512 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
513 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
514 # return nil if( rhs == nil || lhs == nil )
515 return nil if ! evaluable?( rhs, lhs )
516 return lhs > rhs
517 when :OP_LE
518 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
519 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
520 # return nil if( rhs == nil || lhs == nil )
521 return nil if ! evaluable?( rhs, lhs )
522 return lhs <= rhs
523 when :OP_GE
524 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
525 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
526 # return nil if( rhs == nil || lhs == nil )
527 return nil if ! evaluable?( rhs, lhs )
528 return lhs >= rhs
529 when :OP_EQ
530 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
531 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
532 # return nil if( rhs == nil || lhs == nil )
533 return nil if ! evaluable?( rhs, lhs )
534 return lhs.eq( rhs )
535 when :OP_NE
536 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
537 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
538 # return nil if( rhs == nil || lhs == nil )
539 return nil if ! evaluable?( rhs, lhs )
540 return lhs.neq( rhs )
541 when :OP_AND
542 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
543 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
544 # return nil if( rhs == nil || lhs == nil )
545 return nil if ! evaluable?( rhs, lhs )
546 return lhs & rhs
547 when :OP_EOR
548 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
549 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
550 # return nil if( rhs == nil || lhs == nil )
551 return nil if ! evaluable?( rhs, lhs )
552 return lhs ^ rhs
553 when :OP_OR
554 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
555 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
556 # return nil if( rhs == nil || lhs == nil )
557 return nil if ! evaluable?( rhs, lhs )
558 return lhs | rhs
559 when :OP_LAND
560 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
561 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
562 # return nil if( rhs == nil || lhs == nil )
563 return nil if ! evaluable?( rhs, lhs )
564 return lhs.lAND( rhs )
565 when :OP_LOR
566 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
567 rhs = elements_eval_const(elements[2], name_list, name_list2, nest)
568 # return nil if( rhs == nil || lhs == nil )
569 return nil if ! evaluable?( rhs, lhs )
570 return lhs.lOR( rhs )
571 when :OP_CEX
572 lhs = elements_eval_const(elements[1], name_list, name_list2, nest)
573 mhs = elements_eval_const(elements[2], name_list, name_list2, nest)
574 rhs = elements_eval_const(elements[3], name_list, name_list2, nest)
575 # return nil if( rhs == nil || mhs == nil || lhs == nil )
576 return nil if ! evaluable?( rhs, mhs, lhs )
577 if lhs.cast( BoolType.new ).val then
578 return mhs
579 else
580 return rhs
581 end
582 end
583 return nil
584 end
585
586 def elements_get_type( elements, namedList )
587 type = elements_get_type_sub( elements, namedList )
588 # 返された方が DefinedType の場合 å…
589ƒã®åž‹ã‚’返す
590 if type.kind_of?( DefinedType ) then
591 type = type.get_type
592 end
593 return type
594 end
595
596 def elements_get_type_sub( elements, namedList )
597 case elements[0]
598 when :IDENTIFIER
599 nsp = elements[1]
600 if nsp.is_name_only? then
601 paramdecl = namedList.get_item( nsp.get_name )
602 else
603 paramdecl = nil
604 end
605 unless paramdecl then
606 cdl_error( "E1012 $1: not found in parameter list" , nsp.get_path_str )
607 return IntType.new(32) # dummy result
608 end
609 return paramdecl.get_type
610# mikan get_type
611# when :INTEGER_CONSTANT
612# when :FLOATING_CONSTANT
613# when :OCTAL_CONSTANT
614# when :HEX_CONSTANT
615# when :CHARACTER_LITERAL
616# when :STRING_LITERAL_LIST
617# when :PARENTHESES
618# when :OP_SUBSC
619# when :OP_DOT
620# when :OP_REF
621# when :OP_SIZEOF_EXPR
622# when :OP_SIZEOF_TYPE
623# when :OP_U_AMP
624 when :OP_U_ASTER
625 type = elements_get_type( elements[1], namedList )
626 unless type.kind_of?( PtrType ) then
627 cdl_error( "E1013 \'*\': operand is not pointer value" )
628 return IntType.new( 8 ) # IntType を返しておく
629 end
630 return type.get_referto
631
632 when :OP_U_PLUS, :OP_U_MINUS
633 # mikan operand が適切な型かチェックしていない
634 return elements_get_type( elements[1], namedList )
635
636 when :OP_ADD, :OP_SUB, :OP_MULT, :OP_DIV, :OP_REMAIN
637 # mikan operand が適切な型かチェックしていない&左辺の型を採用している
638 return elements_get_type( elements[1], namedList )
639
640 when :OP_U_TILDE
641 # mikan operand が整数かチェックしていない
642 return elements_get_type( elements[1], namedList )
643 when :OP_AND, :OP_EOR, :OP_OR, :OP_LSFT, :OP_RSFT
644 # mikan operand が整数かチェックしていない
645 return BoolType.new
646 when :OP_U_EXCLAM
647 # mikan operand が整数かチェックしていない
648 return BoolType.new
649
650 when :OP_LT, :OP_GT, :OP_LE, :OP_GE, :OP_EQ, :OP_NE, :OP_LAND, :OP_LOR, :OP_CEX, :CAST
651 cdl_error( "E1014 $1: elements_get_type: sorry not supported" , elements[0] )
652 end
653
654 return nil
655 end
656
657 # 式が size_is, count_is, string の引数である場合の方向のチェック
658 def elements_check_dir_for_param( elements, namedList, dir, spec )
659 # dir : å…
660ƒã®å¼•æ•°ã®æ–¹å‘
661 # direct: size_is などの引数の変数の方向
662
663 case elements[0]
664 when :IDENTIFIER
665 nsp = elements[1]
666 if nsp.is_name_only? then
667 paramdecl = namedList.get_item( nsp.get_name )
668 else
669 paramdecl = nil
670 end
671
672 return unless paramdecl # if nil already error in element_get_type
673
674 direct = paramdecl.get_direction
675 judge = false
676 case spec
677 when "size_is", "string"
678 case dir
679 when :IN, :OUT, :INOUT, :SEND
680 judge = true if ( direct == :IN || direct == :INOUT )
681 req_direct = "in or inout"
682 when :RECEIVE
683 judge = true if ( direct == :OUT || direct == :INOUT )
684 req_direct = "out or inout"
685 end
686
687 when "count_is"
688 case dir
689 when :IN, :SEND
690 judge = true if ( direct == :IN || direct == :INOUT )
691 req_direct = "in or inout"
692 when :OUT, :RECEIVE # mikan out で count_is のみ指定されている場合 in でなくてはならない
693 judge = true if ( direct == :OUT || direct == :INOUT )
694 req_direct = "out or inout"
695 when :INOUT
696 judge = true if ( direct == :INOUT )
697 req_direct = "inout"
698 end
699 end
700
701 if judge == false then
702 cdl_error( "E1015 \'$1\': direction mismatch for $2, $3 required" , nsp.get_path_str, spec, req_direct )
703 end
704
705 when :INTEGER_CONSTANT, :FLOATING_CONSTANT, :OCTAL_CONSTANT, :HEX_CONSTANT, :CHARACTER_LITERAL, :STRING_LITERAL_LIST
706 return true
707
708 # 単項
709演算子
710 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,
711 elements_check_dir_for_param( elements[1], namedList, dir, spec )
712
713 # 2項
714演算子
715 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
716 return elements_check_dir_for_param( elements[1], namedList, dir, spec ) && elements_check_dir_for_param( elements[2], namedList, dir, spec )
717
718 # 3項
719演算子
720 when :OP_CEX
721 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 )
722
723 else
724 cdl_error( "E1016 $1: elements_check_dir_for_param: sorry not supported" , elements[0] )
725 end
726
727 end
728
729 #Express# get_allocator_rhs_elem
730 #alloc_type::Symbol :NORMAL_ALLOC|:INTERNAL_ALLOC|:RELAY_ALLOC
731 #式がアロケータ指定子の右辺として妥当かチェックし、正しければ分解した値を返す
732 #return:
733 # :NORMAL_ALLOC [ cell_nsp, ep_name ] # rhs = cell_nsp.ep_name ex) Alloc.eAlloc
734 # :INTERNAL_ALLOC [ ep_name ] # rhs = ep_name ex) eAlloc
735 # :RELAY_ALLOC [ cp_name, func_name, param_name ] # rhs = cp_name.func_name.param_name
736 def get_allocator_rhs_elements( alloc_type )
737 ele = @elements
738 case alloc_type
739 when :NORMAL_ALLOC
740 if ele[0] != :OP_DOT || ele[1][0] != :IDENTIFIER then #1
741 cdl_error( "E1017 $1: rhs not \'Cell.ePort\' form" , ele[0].to_s )
742 return nil
743 end
744 cell_nsp = elements[1][1]
745 port_name = elements[2].val
746 return [ cell_nsp, port_name ]
747 when :INTERNAL_ALLOC
748 if( ele[0] == :IDENTIFIER )then
749 if ele[1].is_name_only? then
750 return [ ele[1].get_path[0] ] # mikan a::b
751 else
752 cdl_error( "E1018 $1: namespace cannot be specified", ele[1].to_s )
753 end
754 else
755 cdl_error( "E1019 $1: rhs not in 'allocator_entry_port' form", ele[1].to_s )
756 end
757 when :RELAY_ALLOC
758 if( ele[0] != :OP_DOT ||
759 ele[1][0] != :OP_DOT || ele[1][1][0] != :IDENTIFIER || ! ele[1][1][1].is_name_only? ||
760 ! ele[1][2].instance_of?( Token ) || ! ele[2].instance_of?( Token ) )then #1
761 cdl_error( "E1020 rhs not in 'call_port.func.param' form ($1)" , ele[0].to_s ) # S1086
762 end
763 func_name = ele[1][2]; cp_name = ele[1][1][1].get_name; param_name = ele[2].to_sym
764 return [ cp_name, func_name, param_name ]
765 end
766 return nil
767 end
768
769 #Expression#Expression のクローンを作成する
770 def clone_for_composite
771 cl = self.clone
772 elements = clone_elements @elements
773 cl.set_elements elements
774 return cl
775 end
776
777 #Expression#elements のクローンを作成
778 #elements::Array
779 # このメソッドは、Array のディープコピーを行う
780 def clone_elements elements
781 elements = elements.clone
782 elements.map!{ |ele|
783 if ele.instance_of? Array
784 clone_elements ele
785 else
786 ele
787 end
788 }
789 return elements
790 end
791
792 def set_elements elements
793 @elements = elements
794 end
795
796 #=== Expression#セル結合の式を解析する
797 # Cell.eEntry => [ :OP_DOT, [ :IDENTIFIER, token ], token ]
798 # Cell.eEntry[expression] => [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, token ], token ], expression ]
799 # Return: [ NamespacePath(cell_name), Integer(subscript) or nil, Token(port_name)]
800 def analyze_cell_join_expression
801 # 右辺の Expression の要素を取り出す
802 elements = @elements
803 if elements[0] == :OP_SUBSC then # 右辺:受け口é…
804åˆ—?
805 # elements = [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, token ], token ], expression ]
806 subscript = elements[2].eval_const(nil) # 受け口é…
807åˆ—の添数
808 elements = elements[1] # mikan é…
809åˆ—だった場合
810 else
811 subscript = nil
812 end
813
814 # elements = [ :OP_DOT, [ :IDENTIFIER, token ], token ]
815 if elements[0] != :OP_DOT || elements[1][0] != :IDENTIFIER then #1
816 return nil
817 end
818
819 nsp = elements[1][1] # NamespacePath
820 port_name = elements[2].val
821
822 return [ nsp, subscript, port_name]
823 end
824
825 #=== Expression# セルへの結合の式を生成する
826 #nsp:: NamespacePath
827 #subscript:: Integer
828 #port_name:: Symbol
829 # analyze_cell_join_expression と対になっている
830 def self.create_cell_join_expression( nsp, subscript, port_name, locale = nil )
831 if ! port_name.instance_of?( Symbol ) then
832 raise "port_name: not Symbol"
833 end
834
835 if subscript then
836 elements = [ :OP_SUBSC, [ :OP_DOT, [ :IDENTIFIER, nsp ],
837 Token.new( port_name, nil, nil, nil ) ],
838 Expression.create_integer_constant( subscript, @locale ) ]
839 else
840 elements = [ :OP_DOT, [ :IDENTIFIER, nsp ], Token.new( port_name, nil, nil, nil ) ]
841 end
842 return Expression.new( elements, locale )
843 end
844
845 #=== Expression#整数定数の式を生成する
846 #val:: Integer : 値: 整数
847 def self.create_integer_constant( val, locale = nil )
848 if val != Integer( val ) || val < 0 then
849 raise "create_integer_constant: not integer or negative: #{val}"
850 end
851 Expression.new( [ :INTEGER_CONSTANT, Token.new( val, nil, nil, nil ) ], locale )
852 end
853
854 #=== Expression#単一の識別子の式を解析する
855 # Identifier => [ :IDENTIFIER, token ]
856 # Return: NamespacePath(Identifier)
857 def analyze_single_identifier
858 # 右辺の Expression の要素を取り出す
859 elements = @elements
860 if elements[0] == :IDENTIFIER
861 return elements[1]
862 else
863 return nil
864 end
865 end
866
867 #=== Expression#
868 #nsp:: NamespacePath : 参ç…
869§ã™ã‚‹ã‚‚の識別子
870 def self.create_single_identifier( nsp, locale )
871 if ! nsp.instance_of?( NamespacePath ) then
872 raise "create_single_identifier: not NamespacePath: #{nsp.to_s}"
873 end
874 Expression.new( [ :IDENTIFIER, nsp ] )
875 end
876
877 #=== 評価可能かチェックする
878 #*v:: 可変個引数(任意の型)
879 # すべてが BaseVal の子クラス(値)であれば、評価可能と判断する
880 def evaluable?( *v )
881 v.each{ |val|
882 if ! val.kind_of?( BaseVal ) then
883 return false
884 end
885 }
886 return true
887 end
888
889 private :elements_to_s, :elements_eval_const, :elements_get_type
890
891end
892
893
894class C_EXP < Node
895# @c_exp_string : string
896
897 #c_exp_string::String
898 #b_renew::Bool : true なら C_EXP の clone 作成(エスケープ処理等をしない)
899 def initialize( c_exp_string, b_renew = false )
900 if b_renew then
901 @c_exp_string = c_exp_string
902 else
903 # 前後の " を取り除く
904 # str = c_exp_string.to_s.sub( /^\"(.*)\"$/, "\\1" )
905 str = CDLString.remove_dquote c_exp_string.to_s
906 @c_exp_string = CDLString.escape str
907 end
908 end
909
910 #=== composite 用に C_EXP を clone する
911 #ct_name::
912 #cell_name::
913 # composite の attribute に現れる C_EXP を文字列置換して生成しなおす.
914 # この文字列置換は、意味解釈段階で行う.
915 # 他の C_EXP の文字列置換は、コード生成段階で行う.
916 def clone_for_composite( ct_name, cell_name, locale )
917 dbgPrint "C_EXP: #{ct_name} #{cell_name} #{@c_exp_string}\n"
918
919 @locale = locale
920 str = @c_exp_string.gsub( /(^|[^\$])\$ct\$/, "\\1#{ct_name}" )
921 str = str. gsub( /(^|[^\$])\$cell\$/, "\\1#{cell_name}" )
922 str = str. gsub( /(^|[^\$])\$id\$/, "\\1#{ct_name}_#{cell_name}" )
923 return C_EXP.new( str, true )
924 end
925
926 def get_c_exp_string
927 @c_exp_string
928 end
929
930 #=== C_EXP を評価する
931 # C_EXP の引き数文字列を返す
932 # 本来 C_EXP は eval_const する対象ではないが、便宜上 eval_const で対応
933 def eval_const( name_list, name_list2 = nil )
934 return self
935 end
936 def eval_const2( name_list, name_list2 = nil, nest = nil )
937 return self
938 end
939
940 def to_s
941 @c_exp_string
942 end
943
944 def to_CDL_str
945 return "C_EXP( \"#{to_s}\" )"
946 end
947
948 def show_tree( indent )
949 indent.times { print " " }
950 puts "C_EXP: #{@c_exp_string}"
951 end
952end
953
Note: See TracBrowser for help on using the repository browser.