source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/expression.rb@ 321

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

文字コードを設定

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