source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tecsgen/tecslib/core/expression.rb@ 359

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

SDカードの挿抜を検知するよう更新

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