source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/types.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: 42.5 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2015 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
40#= HasType: @type を内部に持つ型のためのモジュール
41# @b_cloned::Bool : true if @type is cloned
42#
43# このモジュールは DefinedType, PtrType, ArrayType に include される
44# 本当は typedef された時の Decl の要素のみ clone すればよいのだが、get_type, get_original_type で
45# 取り出されたとき、set_scs, set_qualifier されたときに無条件で clone する (無駄にメモリを使用する)
46# ただし、clone するのは一回のみである (二回 clone すると別の型を参照してしまう)
47#
48# initialize で clone しても、共有されているときに clone されない
49#
50module HasType
51 def initHasType
52 @b_cloned = false
53 end
54
55 #=== HasType# @type をクローンする
56 def clone_type
57# if @b_cloned == false then
58 @type = @type.clone
59 @b_cloned = true
60# end
61 end
62end
63
64class Type < Node
65# @b_const : bool
66# @b_volatile : bool
67
68 def initialize
69 super
70 end
71
72 def set_qualifier( qualifier )
73 case qualifier
74 when :CONST
75# if @b_const then
76# cdl_error( "T1001 const duplicate" )
77# end
78 @b_const = true
79 when :VOLATILE
80# if @b_volatile then
81# cdl_error( "T1002 volatile duplicate" )
82# end
83 @b_volatile = true
84 else
85 raise "Unknown qualifier #{qualifier}"
86 end
87 end
88
89 def is_const?
90 if @b_const then
91 return true
92 else
93 return false
94 end
95 end
96
97 def is_volatile?
98 if @b_volatile then
99 return true
100 else
101 return false
102 end
103 end
104
105 def is_void?
106 if self.kind_of? DefinedType then
107 return @type.is_void?
108 elsif self.kind_of? VoidType then
109 return true
110 else
111 return false
112 end
113 end
114
115 #=== size_is, count_is, string を設定
116 # 派生クラスでオーバーライドする(デフォルトではエラー)
117 def set_scs( size, count, string, max = nil, b_nullable = false )
118 str = ""
119 delim = ""
120 if size then
121 str = "size_is"
122 delim = ", "
123 end
124 if count then
125 str = "#{str}#{delim}count_is"
126 delim = ", "
127 end
128 if string then
129 str = "#{str}#{delim}string"
130 delim = ", "
131 end
132 if b_nullable then
133 str = "#{str}#{delim}nullable"
134 delim = ", "
135 end
136 cdl_error( "T1003 $1: unsuitable specifier for $2" , str, self.class )
137 end
138
139 def clear_max
140 raise "clear_max called: #{self.class}"
141 end
142
143 def get_type_str
144 str = ""
145 if @b_const then
146 str = "#{str}const "
147 end
148 if @b_volatile then
149 str = "#{str}volatile "
150 end
151 return str
152 end
153
154 #=== 型をチェック
155 # 正当な型定義かどうか、チェックする
156 def check
157 # 型に誤りがあれば、エラー文字列を返す
158 end
159
160 #=== struct の tag をチェック
161 # 正当な型定義かどうか、チェックする
162 #kind:: Decl の @kind を参照
163 def check_struct_tag kind
164 # tag が存在しなければエラーを出力する
165 # 配列型では、要素の型を再帰的にチェック
166 # ポインタ型では、指す先の tag チェックはしない
167 # 関数型ではパラメータリストのすべてについて行う
168 end
169
170 #=== 初期化可能かチェック
171 # attribute など初期化可能かチェックする(型に対し正当な初期化子が与えられているか)
172 #ident:: string 被代入変数命
173 #initialize:: Expression, Array of initializer or C_EXP
174 # 代入値、C_EXP が与えられるのは IntType の場合のみ
175 #kind:: symbol (:ATTRIBUTE, :VAR, :CONSTNAT )
176 #attribute:: NameList kind == :VAR のとき参照できる attribute
177 #
178 # locale を第一引数として取るのは、以下の理由による。
179 # このメソッドは、変数への代入が行われる「行」に対して呼び出されるが、
180 # Type クラスのインスタンスは、変数が定義された「行」を記憶している。
181 #
182 # STAGE: S
183 def check_init( locale, ident, initializer, kind, attribute = nil )
184 #
185 end
186
187 #=== const_val を指定の型にキャストする
188 # 派生クラスでオーバーライドしていないとエラー
189 def cast( const_val )
190 cdl_error( "T1004 cannot cast to $1" , self.class )
191 end
192
193 #=== 型が一致するかのチェック
194 # 型名の字面でチェック.
195 # typedef された型も字面で一致を見るため、元の型が同じでも型名が異なれば不一致となる
196 def equal? type2
197 return ( get_type_str == type2.get_type_str ) && ( get_type_str_post == type2.get_type_str_post )
198 end
199
200 #=== bit size を得る
201 # IntType, FloatType 以外は0
202 def get_bit_size
203 return 0
204 end
205
206 #=== 元の型を得る
207 # typedef された型の場合、その元の型を返す.
208 # それ以外は、自分自身を返す.
209 # (DefinedType では本メソッドがオーバーライドされる)
210 def get_original_type
211 return self
212 end
213
214 #=== 内部にポインタ型を持つ
215 # ポインタ型、またはポインタ型メンバを持つ構造体、または要素がポインタ型を持つ配列
216 def has_pointer?
217 false
218 end
219
220 #=== size_is, count_is, string 指定されたポインタを持つか
221 # size_is, count_is, string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれをを要素に持つ配列
222 def has_sized_pointer?
223 false
224 end
225
226 #=== 長さ指定のない string を持つ
227 # なさ指定のない string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれを要素に持つ配列
228 def has_unsized_string?
229 false
230 end
231
232 def show_tree indent
233 indent.times { print " " }
234 puts "const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
235 indent.times { print " " }
236 puts "has_pointer=#{has_pointer?} has_sized_pointer=#{has_sized_pointer?} has_unsized_string=#{has_unsized_string?}"
237 end
238end
239
240class DefinedType < Type
241# @type_name::string
242# @typedef::Typedef
243# @type:: kind_of Type
244
245 include HasType
246
247 def initialize( type_name )
248 super()
249 @type_name = type_name
250
251 # mikan type_name が path になっていないため暫定
252 @typedef = Namespace.find( [ type_name ] ) #1
253
254# if @type.class != Typedef then
255# raise NotTypedef
256 # end
257 if @typedef == nil then
258 cdl_error( "T1005 \'$1\' not defined" , type_name )
259 elsif @typedef.class != Typedef then
260 cdl_error( "T1006 \'$1\' not type name. expecting type name here" , type_name )
261 end
262 @type = @typedef.get_declarator.get_type
263 initHasType
264 end
265
266 def get_type
267 clone_type
268 return @type
269 end
270
271 def get_type_str
272 "#{super}#{@type_name}"
273 end
274
275 def get_type_str_post
276 ""
277 end
278
279 def get_size
280 return @type.get_size
281 end
282
283 def is_nullable?
284 return @type.is_nullable?
285 end
286
287 #=== qualifier(const, volatile) の設定
288 def set_qualifier( qualifier )
289 clone_type
290 @type.set_qualifier( qualifier )
291 super
292 end
293
294 def set_scs( size, count, string, max = nil, b_nullable = false )
295 clone_type
296 @type.set_scs( size, count, string, max, b_nullable )
297 end
298
299 def clear_max
300 @type.clear_max
301 end
302
303 def get_original_type
304 clone_type
305 return @type.get_original_type
306 end
307
308 def check # 意味的誤りがあれば、文字列を返す
309 nil # typedef の段階で意味チェックされている
310 end
311
312 def check_init( locale, ident, initializer, kind, attribute = nil )
313 get_type.check_init( locale, ident, initializer, kind, attribute )
314 end
315
316 #=== 内部にポインタ型を持つ
317 # ポインタ型、またはポインタ型メンバを持つ構造体、または要素がポインタ型を持つ配列
318 def has_pointer?
319 @type.has_pointer?
320 end
321
322 #=== size_is, count_is, string 指定されたポインタを持つか
323 # size_is, count_is, string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれをを要素に持つ配列
324 def has_sized_pointer?
325 @type.has_sized_pointer?
326 end
327
328 #=== 長さ指定のない string を持つ
329 # なさ指定のない string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれを要素に持つ配列
330 def has_unsized_string?
331 @type.has_unsized_string?
332 end
333
334 def show_tree( indent )
335 indent.times { print " " }
336 if @typedef == nil then
337 puts "DefinedType: #{@type_name} is missing, const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
338 else
339 puts "DefinedType: #{@type_name}, const=#{@b_const} volatile=#{@b_volatile}"
340 end
341 super( indent + 1 )
342 @typedef.show_tree( indent + 1 )
343 @type.show_tree( indent + 1 )
344 end
345end
346
347class VoidType < Type
348
349 def check # 意味的誤りがあれば、文字列を返す
350 nil
351 end
352
353 def check_init( locale, ident, initializer, kind, attribute = nil )
354 cdl_error2( locale, "T1007 $1: void type variable cannot have initializer" , ident )
355 end
356
357 def get_type_str
358 "#{super}void"
359 end
360
361 def get_type_str_post
362 ""
363 end
364
365 def show_tree( indent )
366 indent.times { print " " }
367 puts "VoidType #{locale_str}"
368 super( indent + 1 )
369 end
370end
371
372class BoolType < Type
373
374 def check # 意味的誤りがあれば、文字列を返す
375 nil
376 end
377
378 def get_type_str
379 "#{super}bool_t"
380 end
381
382 def get_type_str_post
383 ""
384 end
385
386 def show_tree( indent )
387 indent.times { print " " }
388 puts "BoolType #{locale_str}"
389 super( indent + 1 )
390 end
391end
392
393class IntType < Type
394# @bit_size:: -11: char, -1: char_t, -2: short, -3: int, -4: long, -5: long long
395# 8, 16, 32, 64, 128
396# @sign:: :SIGNED, :UNSIGNED, nil
397
398 def initialize( bit_size )
399 super()
400 @bit_size = bit_size
401 @sign = nil
402 end
403
404 def set_sign( sign, b_uint = false )
405 if @sign then
406 if @sign != sign then
407 cdl_error( "T1008 ambigous signed or unsigned" )
408 end
409 elsif b_uint == false && @bit_size > 0 then
410 if sign == :SIGNED then
411 cdl_warning( "W2001 signed int$1_t: obsolete. use int$2_t" , @bit_size, @bit_size )
412 else
413 cdl_warning( "W2002 unsinged int$1_t: obsolete. use uint$2_t" , @bit_size, @bit_size )
414 end
415 end
416
417 @sign = sign
418
419 if @sign != :SIGNED && @sign != :UNSIGNED then
420 raise "set_sign: unknown sign: #{@sign}"
421 end
422 end
423
424 def check # 意味的誤りがあれば、文字列を返す
425 nil
426 end
427
428 def check_init( locale, ident, initializer, kind, attribute = nil )
429 val = initializer # C_EXP, Array
430 if val.instance_of?( Expression ) then
431 val = val.eval_const2( nil, attribute )
432 # 評価の結果 C_EXP や Array となる可能性がある
433 end
434
435 if val.instance_of? Token then # StringVal 導入により、もはや Token は来ないはず
436 # val が Token の場合 == の右辺が String だとエラーを起こす (#198)
437 cdl_error2( locale, "T1009 $1: $2: not integer" , ident, val )
438 return
439 elsif val.is_a? C_EXP then
440 # #192 var が attribute を参照し、attribute の右辺が C_EXP の場合
441 # const の右辺が C_EXP の場合も
442 return
443 elsif val.kind_of? FloatVal then
444 cdl_error2( locale, "T1011 $1: need cast to assign float to integer" , ident )
445 return
446 elsif val.instance_of? Array then
447 cdl_error2( locale, "T1017 $1: unsuitable initializer for scalar type" , ident )
448 return
449 elsif val == nil then
450 cdl_error2( locale, "T1010 $1: initializer is not constant" , ident )
451 return
452 end
453
454 if ! val.kind_of? IntegerVal then
455 cdl_error2( locale, "T1012 $1: $2: not integer" , ident, val )
456 return
457 end
458
459 val = val.to_i
460 max = get_max
461 min = get_min
462 dbgPrint "sign=#{@sign} ident=#{ident} val=#{val} max=#{max} min=#{min}\n"
463
464 if max != nil then
465 if val > max then
466 if @sign == :SIGNED || @sign == nil then
467 cdl_error2( locale, "T1013 $1: too large (max=$2)" , ident, max )
468 else
469 cdl_error2( locale, "T1016 $1: too large (max=$2)" , ident, max )
470 end
471 end
472 end
473
474 if min != nil then
475 if val < min
476 if @sign == :SIGNED || @sign == nil then
477 cdl_error2( locale, "T1014 $1: too large negative value (min=$2)" , ident, min )
478 else
479 cdl_error2( locale, "T1015 $1: negative value for unsigned" , ident )
480 end
481 end
482 end
483 end
484
485 #=== IntType# 最大値、最小値をチェックしてクリップする
486 # キャスト演算を行う
487 #in_val:: IntegerVal, FloatVal: この型にキャストする値
488 #from_type:: Symbol: :IntType, :FloatType IntType の場合はビット数でクリップ、FloatType の場合は最大値でクリップ
489 def check_and_clip( in_val, from_type = :IntType )
490 bit_size = get_bit_size
491 if bit_size == -1 then
492 bit_size = 8
493 end
494 val = in_val.to_i
495 if get_max && val > get_max then
496 if from_type == :IntType then
497 rval = ((1 << bit_size)-1) & val # bit 数でクリップ
498 else
499 rval = get_max # 最大値でクリップ (FloatType)
500 end
501 cdl_warning( "W2003 $1: too large to cast to $2, clipped($3)" , in_val, get_type_str, rval )
502 elsif get_min && val < get_min then
503 if from_type == :IntType then
504 rval = ((1 << bit_size)-1) & val
505 else
506 rval = get_min
507 end
508 if @sign == :SIGNED || @sign == nil then
509 cdl_warning( "W2004 $1: too small to cast to $2, clipped($3)" , in_val, get_type_str, rval )
510 else # @sign == :UNSIGNED || @sign == nil (char の場合)
511 cdl_warning( "W2005 $1: negative value for unsigned: convert to $2" , in_val, rval )
512 end
513 else
514 rval = val
515 end
516 return rval
517 end
518
519 def get_min
520 if @sign == :SIGNED || @sign == nil then
521 if @bit_size == -1 then
522 bit_sz = 8 # char_t は、有符号に扱う
523 else
524 bit_sz = @bit_size
525 end
526 case bit_sz
527 when 8, 16, 32, 64, 128
528 return - ( 1 << ( bit_sz - 1 ))
529 else # -1, -2, -3, -4, -5, -11
530 return nil
531 end
532 else # @sign == :UNSIGNED
533 return 0
534 end
535 end
536
537 def get_max
538 if @bit_size == -1 then
539 if @sign == nil then
540 return 255 # char_t は、無符号に扱う
541 else
542 bit_sz = 8
543 end
544 else
545 bit_sz = @bit_size
546 end
547 if @sign == :SIGNED || @sign == nil then
548 case bit_sz
549 when 8, 16, 32, 64, 128
550 return ( 1 << ( bit_sz - 1 )) -1
551 else # -1, -2, -3, -4, -5, -11
552 return nil
553 end
554 else # @sign == :UNSIGNED
555 case bit_sz
556 when 8, 16, 32, 64, 128
557 return ( 1 << bit_sz ) - 1
558 else # -2, -3, -4, -5, -11
559 return nil
560 end
561 end
562 end
563
564 #=== IntType# C 言語における型名(修飾子付き)
565 def get_type_str
566 str = super
567
568 # NEW_MODE
569 case @sign
570 when :SIGNED
571 sign = ""
572 signL = "signed "
573 when :UNSIGNED
574 sign = "u"
575 signL = "unsigned "
576 else
577 sign = ""
578 signL = ""
579 end
580
581 # p "get_type_str: sign:#{@sign} signL=#{signL}"
582
583 case @bit_size
584 when -1 # char_t 型
585 if @sign == :SIGNED then
586 sign = "s"
587 end
588 str = "#{str}#{sign}char_t"
589 when -11 # char 型(obsolete)
590 str = "#{str}#{signL}char"
591 when -2 # short 型
592 str = "#{str}#{signL}short"
593 when -3 # int 型
594 str = "#{str}#{signL}int"
595 when -4 # long 型
596 str = "#{str}#{signL}long"
597 when -5 # long long 型
598 str = "#{str}#{signL}long long"
599 when 8, 16, 32, 64, 128 # int16, int32, int64, int128 型
600 str = "#{str}#{sign}int#{@bit_size}_t"
601 end
602
603 return str
604 end
605
606 #=== IntType# C 言語における型名(後置文字列)
607 def get_type_str_post
608 ""
609 end
610
611 #=== IntType#bit_size を得る
612 # 返される値は @bit_size の仕様を参照
613 def get_bit_size
614 return @bit_size
615 end
616
617 #=== IntType# sign を得る
618 # @sign の説明を参照
619 def get_sign
620 @sign
621 end
622
623 def show_tree( indent )
624 indent.times { print " " }
625 puts "IntType bit_size=#{@bit_size} sign=#{@sign} const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
626 super( indent + 1 )
627 end
628end
629
630class FloatType < Type
631# @bit_size:: 32, 64, (80), -32, -64
632
633 def initialize( bit_size )
634 super()
635 @bit_size = bit_size
636 end
637
638 def check # 意味的誤りがあれば、文字列を返す
639 nil
640 end
641
642 # mikan Float 型の C_EXP 対応 (generate.rb にも変更必要)
643 def check_init( locale, ident, initializer, kind, attribute = nil )
644 # 型に対する初期値に誤りがあれば、エラー文字列を返す
645 val = initializer
646 if val.instance_of?( Expression ) then
647 val = val.eval_const2( nil, attribute )
648 # 評価の結果 C_EXP や Array となる可能性がある
649 end
650
651 if val.instance_of? Token then
652 # val が Token の場合 == の右辺が String だとエラーを起こす
653 cdl_error2( locale, "T1018 $1: $2: not number" , ident, val )
654 return
655 elsif val.instance_of? Array then
656 cdl_error2( locale, "T1020 $1: unsuitable initializer for scalar type" , ident )
657 return
658 elsif val.instance_of? C_EXP then
659 return
660 elsif val == nil then
661 cdl_error2( locale, "T1019 $1: initializer is not constant" , ident )
662 return
663 elsif ! val.kind_of?( IntegerVal ) && ! val.kind_of?( FloatVal ) then
664 cdl_error2( locale, "T1037 $1: not number" , ident )
665 return
666 end
667 # else
668 # cdl_error2( locale, "T1020 $1: unsuitable initializer for scalar type" , ident )
669 # return
670 # end
671 return
672 end
673
674 def get_type_str
675 str = super
676
677 case @bit_size
678 when 32
679 str = "#{str}float32_t"
680 when 64
681 str = "#{str}double64_t"
682 when -32
683 str = "#{str}float"
684 when -64
685 str = "#{str}double"
686 end
687 return str
688 end
689
690 def get_type_str_post
691 ""
692 end
693
694 def get_bit_size
695 @bit_size
696 end
697
698 def show_tree( indent )
699 indent.times { print " " }
700 puts "FloatType bit_size=#{@bit_size} qualifier=#{@qualifier} #{locale_str}"
701 super( indent + 1 )
702 end
703end
704
705class EnumType < Type # mikan
706# @bit_size:: -1: enum
707# 8, 16, 32, 64, 128
708# @element:: []
709# @element_val:: []
710
711 def initialize( bit_size )
712 super()
713 @bit_size = bit_size
714 end
715
716 def check
717 # mikan enum check
718 end
719
720 def show_tree( indent )
721 indent.times { print " " }
722 puts "EnumType bit_size=#{@bit_size} qualifier=#{@qualifier} #{locale_str}"
723 super( indent + 1 )
724 # mikan element
725 end
726end
727
728class StructType < Type
729# @tag::
730# @b_define:: true if define, false if refer
731# @members_decl:: NamedList
732# @definition:: StructType
733# @b_has_pointer_member:: bool : メンバにポインタ型がある
734# @b_has_sized_pointer_member:: bool : メンバにポインタ型がある
735# @b_has_unsized_string_member:: bool : メンバにポインタ型がある
736# @member_types_symbol:: Symbol : tag が無い時のみ設定 (それ以外では nil)
737
738 @@structtype_current_stack = []
739 @@structtype_current_sp = -1
740
741 # tag なし struct
742 @@no_struct_tag_num = 0
743 @@no_tag_struct_list = {}
744
745 def initialize( tag = nil )
746 super()
747 @tag = tag
748 @@structtype_current_sp += 1
749 @@structtype_current_stack[@@structtype_current_sp] = self
750 @b_has_pointer_member = false
751 @b_has_sized_pointer_member = false
752 @b_has_unsized_string_member = false
753 @member_types_symbol = nil
754 end
755
756 def self.set_define( b_define )
757 @@structtype_current_stack[@@structtype_current_sp].set_define( b_define )
758 end
759
760 def set_define( b_define )
761 @b_define = b_define
762 if @b_define then
763 @members_decl = NamedList.new( nil, "in struct #{@tag}" )
764 # if @tag then 登録タイミングを終わりに変更 V1.0.2.19
765 # Namespace.new_structtype( self )
766 # end
767 else
768 @definition = Namespace.find_tag( @tag )
769 # check_struct_tag に移す V1.0.2.19
770 # if @definition == nil then
771 # cdl_error( "T1021 \'$1\': struct not defined" , @tag )
772 # end
773 end
774 end
775
776 def self.new_member( member_decl )
777 @@structtype_current_stack[@@structtype_current_sp].new_member( member_decl )
778 end
779
780 def new_member( member_decl )
781 member_decl.set_owner self # Decl (StructType)
782 @members_decl.add_item( member_decl )
783 if member_decl.get_type.has_pointer?
784 @b_has_pointer_member = true
785 end
786 if member_decl.get_type.has_sized_pointer?
787 @b_has_sized_pointer_member = true
788 end
789 if member_decl.get_type.has_unsized_string?
790 @b_has_unsized_string_member = true
791 end
792 end
793
794 def check # 意味的誤りがあれば、文字列を返す
795 nil
796 end
797
798 #=== 構造体のタグをチェック
799 # declarator の時点でチェックする
800 #kind:: Decl の @kind を参照
801 def check_struct_tag kind
802 if @tag == nil
803 return
804 end
805
806 st = Namespace.find_tag( @tag )
807 if st == nil then
808 cdl_error( "T1022 struct $1: not defined" , @tag )
809 end
810 end
811
812 # mikan Float 型の C_EXP 対応 (generate.rb にも変更必要)
813 def check_init( locale, ident, initializer, kind, attribute = nil )
814
815 st = Namespace.find_tag( @tag )
816 if st == nil then
817 cdl_error2( locale, "T1023 struct $1: not defined" , @tag )
818 return
819 end
820
821 # 初期化子が式の場合、型(タグ)が一致するかチェック
822 if initializer.instance_of?( Expression ) then
823 t = initializer.get_type( attribute )
824 # print "Check init #{t.class} #{t.get_name}\n"
825 if ! t.kind_of?( StructType ) then
826 if t then
827 str = t.get_type_str
828 else
829 str = "unknown"
830 end
831 cdl_error2( locale, "T1038 $1: initializer type mismatch. '$2' & '$3'" , ident, get_type_str, str )
832 elsif @tag != t.get_name then
833 cdl_error2( locale, "T1039 $1: struct tag mismatch $2 and $3" , ident, @tag, t.get_name )
834 end
835 initializer = initializer.eval_const( attribute )
836 end
837
838 if initializer.instance_of?( Array ) then
839 i = 0
840 st.get_members_decl.get_items.each { |d|
841 if initializer[i] then
842 d.get_type.check_init( locale, "#{ident}.#{d.get_identifier}", initializer[i], kind )
843 end
844 i += 1
845 }
846 else
847 cdl_error2( locale, "T1024 $1: unsuitable initializer for struct" , ident )
848 end
849 end
850
851 def self.end_of_parse()
852 @@structtype_current_stack[@@structtype_current_sp].end_of_parse
853 @@structtype_current_sp -= 1
854 end
855
856 def end_of_parse()
857 if @members_decl == nil # @b_define = false またはメンバーのない構造体(エラー)
858 return
859 end
860 @members_decl.get_items.each{ |md|
861 size = md.get_size_is
862 if size then
863 val = size.eval_const( @members_decl )
864 if val == nil then
865 type = size.get_type( @members_decl )
866 if ! type.kind_of?( IntType ) then
867 cdl_error( "T1025 size_is argument is not integer type" )
868 end
869 end
870 end
871 count = md.get_count_is
872 if count then
873 val = count.eval_const( @members_decl )
874 if val == nil then
875 type = count.get_type( @members_decl )
876 if ! type.kind_of?( IntType ) then
877 cdl_error( "T1026 count_is argument is not integer type" )
878 end
879 end
880 end
881 string = md.get_string
882 if string == -1 then
883 # 長さ指定なし
884 elsif string then
885 val = string.eval_const( @members_decl )
886 if val == nil then
887 type = string.get_type( @members_decl )
888 if ! type.kind_of?( IntType ) then
889 cdl_error( "T1027 string argument is not integer type" )
890 end
891 end
892 end
893 }
894
895 if @tag == nil then
896 @member_types_symbol = get_member_types_symbol
897 # print "member_types_symbol = #{get_member_types_symbol}\n"
898 if @@no_tag_struct_list[ @member_types_symbol ] then
899 @tag = @@no_tag_struct_list[ @member_types_symbol ]
900 else
901 @tag = :"TAG_#{@@no_struct_tag_num}_TECS_internal__"
902 @@no_struct_tag_num += 1
903 @@no_tag_struct_list[ @member_types_symbol ] = @tag
904 Namespace.new_structtype( self )
905 end
906 else
907 if @b_define then
908 Namespace.new_structtype( self )
909 end
910 end
911 end
912
913 def get_name
914 @tag
915 end
916
917 def get_type_str # mikan struct get_type_str
918 str = super
919
920 if @tag then
921 # typedef struct tag StructType; の形式の場合
922 # struct の本体は、別に生成される
923 return "#{str}struct #{@tag} "
924
925 else
926 # typedef struct { int a; } StructType; の形式の場合
927 str += "struct {\n"
928 @members_decl.get_items.each{ |i|
929 str += sprintf( " %-8s %s%s;\n", "#{i.get_type.get_type_str}", "#{i.get_name}", "#{i.get_type.get_type_str_post}" )
930 }
931 str += "} "
932
933 return str
934
935 end
936 end
937
938 def get_type_str_post
939 ""
940 end
941
942 def get_members_decl
943 return @members_decl if @members_decl
944
945 st = Namespace.find_tag( @tag )
946 if st then
947 return st.get_members_decl
948 end
949
950 return nil
951 end
952
953 def has_pointer?
954 if @definition
955 return @definition.has_pointer?
956 else
957 return @b_has_pointer_member
958 end
959 end
960
961 def has_sized_pointer?
962 if @definition
963 return @definition.has_sized_pointer?
964 else
965 return @b_has_sized_pointer_member
966 end
967 end
968
969 def has_unsized_string?
970 if @definition
971 return @definition.has_unsized_string?
972 else
973 return @b_has_unsized_string_member
974 end
975 end
976
977 #=== 同じ構造体かどうかチェックする
978 # tag のチェックは行わない
979 # すべてのメンバの名前と型が一致することを確認する
980 def same? another
981 md = another.get_members_decl
982 if @members_decl == nil || md == nil
983 return false
984 end
985
986 md1 = @members_decl.get_items
987 md2 = md.get_items
988 if( md1.length != md2.length )
989 return false
990 end
991
992 i = 0
993 while i < md1.length
994 if md1[i].get_name != md2[i].get_name ||
995 md1[i].get_type.get_type_str != md2[i].get_type.get_type_str ||
996 md1[i].get_type.get_type_str_post != md2[i].get_type.get_type_str_post
997 return false
998 end
999 i += 1
1000 end
1001
1002 return true
1003 end
1004
1005 def get_member_types_symbol
1006 mts = ''
1007 @members_decl.get_items.each { |member|
1008 mts += member.get_type.get_type_str + member.get_type.get_type_str_post + ';'
1009 }
1010 return mts.to_sym
1011 end
1012
1013 def show_tree( indent )
1014 indent.times { print " " }
1015 puts "StructType tag: #{@tag} qualifier=#{@qualifier} has_pointer=#{@b_has_pointer_member} #{locale_str}"
1016 super( indent + 1 )
1017 if @b_define then
1018 @members_decl.show_tree( indent + 1 )
1019 end
1020 end
1021end
1022
1023class FuncType < Type
1024# @paramlist:: ParamList
1025# @type:: return type : PtrType, ArrayType, FuncType, IntType, FloatType, ...
1026# @b_oneway:: bool: true, false
1027# @has_in:: bool : has [in] parameter
1028# @has_inout:: bool : has [inout] parameter
1029# @has_out:: bool : has [out] parameter
1030# @has_send:: bool : has [send] parameter
1031# @has_receive:: bool : has [receive] parameter
1032
1033 def initialize( paramlist = nil )
1034 super()
1035
1036 @has_in = false
1037 @has_inout = false
1038 @has_out = false
1039 @has_send = false
1040 @has_receive = false
1041
1042 @paramlist = paramlist
1043 @b_oneway = false
1044 if paramlist then
1045 paramlist.check_param
1046 else
1047 @paramlist = ParamList.new( nil )
1048 end
1049 @paramlist.set_owner self # ParamList
1050 @paramlist.get_items.each{ |p|
1051 case p.get_direction
1052 when :IN
1053 @has_in = true
1054 when :INOUT
1055 @has_inout = true
1056 when :OUT
1057 @has_out = true
1058 when :SEND
1059 @has_send = true
1060 when :RECEIVE
1061 @has_receive = true
1062 else
1063 raise "unkown direction"
1064 end
1065 }
1066
1067 end
1068
1069 def check # 意味的誤りがあれば、文字列を返す
1070 if @type.class == ArrayType then # 配列を返す関数
1071 return "function returning array"
1072 elsif @type.class == FuncType then # 関数を返す関数
1073 return "function returning function"
1074 end
1075 return @type.check # 関数の return する型のチェック
1076
1077 # パラメータの型のチェックは ParamList#check_param で行う
1078 end
1079
1080 def check_struct_tag kind
1081 @type.check_struct_tag kind
1082 # ParamDecl でもチェックされるので、ここではチェックしない
1083 # @paramlist.check_struct_tag kind
1084 end
1085
1086 def check_init( locale, ident, initializer, kind, attribute = nil )
1087 cdl_error2( locale, "T1028 $1: cannot initialize function pointer" , ident )
1088 return
1089 end
1090
1091 def set_type( type )
1092 unless @type then
1093 @type = type
1094 else
1095 @type.set_type( type )
1096 end
1097 end
1098
1099 #=== return type を返す
1100 #
1101 # return type を返す
1102 # get_return_type とすべきだった
1103 def get_type
1104 @type
1105 end
1106
1107 def get_type_str
1108 return @type.get_type_str
1109 end
1110
1111 def get_type_str_post
1112 # 型だけを返す (仮引数の名前を含めない)
1113 @paramlist.to_str( false )
1114 end
1115
1116 def get_paramlist
1117 @paramlist
1118 end
1119
1120 def set_oneway( b_oneway )
1121 @b_oneway = b_oneway
1122
1123 if ( ( @type.get_type_str != "ER" && @type.get_type_str != "void" ) || @type.get_type_str_post != "" ) then
1124 cdl_error( "T1029 oneway function cannot return type \'$1$2\', \'void\' or \'ER\' is permitted" , @type.get_type_str, @type.get_type_str_post )
1125 end
1126
1127 if @paramlist then
1128 @paramlist.get_items.each{ |p|
1129 if p.get_direction != :IN && p.get_direction != :SEND then
1130 cdl_error( "T1030 oneway function cannot have $1 parameter for \'$2\'" , p.get_direction, p.get_name )
1131 end
1132 }
1133 end
1134 end
1135
1136 def is_oneway?
1137 @b_oneway
1138 end
1139
1140 #=== Push Pop Allocator が必要か?
1141 # Transparent RPC の場合 oneway かつ in の配列(size_is, count_is, string のいずれかで修飾)がある
1142 def need_PPAllocator?( b_opaque = false )
1143 if @b_oneway || b_opaque then
1144 return @paramlist.need_PPAllocator?( b_opaque )
1145 else
1146 return false
1147 end
1148 end
1149
1150 #=== パラメータが in, inout, out, send, receive を持つか
1151 def has_in?
1152 @has_in
1153 end
1154 def has_inout?
1155 @has_inout
1156 end
1157 def has_out?
1158 @has_out
1159 end
1160 def has_send?
1161 @has_send
1162 end
1163 def has_receive?
1164 @has_receive
1165 end
1166
1167 #=== 入力方向のパラメータを持つか
1168 def has_inward?
1169 @has_in || @has_inout || @has_send
1170 end
1171 #=== 出力方向のパラメータを持つか
1172 def has_outward?
1173 @has_inout || @has_out || @has_receive
1174 end
1175
1176 def show_tree( indent )
1177 indent.times { print " " }
1178 if @b_oneway then
1179 puts "FunctType: oneway=true #{locale_str}"
1180 else
1181 puts "FunctType: oneway=false #{locale_str}"
1182 end
1183 super( indent + 1 )
1184 if @paramlist then
1185 @paramlist.show_tree( indent + 1 )
1186 end
1187 (indent+1).times { print " " }
1188 puts "return type:"
1189 @type.show_tree( indent + 2 )
1190 end
1191end
1192
1193class ArrayType < Type
1194# @type:: element type : ArrayType, FuncType, IntType, FloatType, ...
1195# @subscript:: Expression, nil if '[]'
1196
1197 include HasType
1198
1199 def initialize( subscript = nil )
1200 super()
1201 @subscript = subscript
1202 initHasType
1203 end
1204
1205 def set_type( type )
1206 unless @type then
1207 @type = type
1208 else
1209 @type.set_type( type )
1210 end
1211 end
1212
1213 #=== Array#qualifier(const, volatile) の設定
1214 def set_qualifier( qualifier )
1215 clone_type
1216 @type.set_qualifier( qualifier )
1217 super
1218 end
1219
1220 # 配列要素が const なら const
1221 def is_const?
1222 @type.is_const?
1223 end
1224
1225 # 配列要素が volatile なら volatile
1226 def is_volatile?
1227 @type.is_volatile?
1228 end
1229
1230 def get_type
1231 @type
1232 end
1233
1234 def get_subscript
1235 @subscript
1236 end
1237
1238 def get_type_str
1239 return "#{@type.get_type_str}"
1240 end
1241
1242 def get_type_str_post
1243 if @subscript
1244 "[#{@subscript.eval_const(nil)}]#{@type.get_type_str_post}"
1245 else
1246 "[]#{@type.get_type_str_post}"
1247 end
1248 # "[#{@subscript.to_s}]#{@type.get_type_str_post}"
1249 end
1250
1251 def check # 意味的誤りがあれば、文字列を返す
1252 if @type.class == FuncType then # 関数の配列
1253 return "array of function"
1254 elsif @type.class == ArrayType then # 添数なし配列の配列
1255 unless @type.get_subscript then
1256 return "subscript not specified"
1257 end
1258 end
1259
1260 return @type.check # 配列要素の型をチェック
1261 end
1262
1263 def check_struct_tag kind
1264 @type.check_struct_tag kind
1265 end
1266
1267 def check_init( locale, ident, initializer, kind, attribute = nil )
1268 if ( initializer.instance_of?( Array ) ) then
1269 index = 0
1270 initializer.each{ |i|
1271 @type.check_init( locale, "#{ident}[#{index}]", i, kind, attribute = nil )
1272 index += 1
1273 }
1274 else
1275 cdl_error2( locale, "T1031 $1: unsuitable initializer for array" , ident )
1276 end
1277 end
1278
1279 def has_pointer?
1280 @type.has_pointer?
1281 end
1282
1283 def has_sized_pointer?
1284 @type.has_sized_pointer?
1285 end
1286
1287 def has_unsized_string?
1288 @type.has_unsized_string?
1289 end
1290
1291 def show_tree( indent )
1292 indent.times { print " " }
1293 puts "ArrayType: #{locale_str}"
1294 super( indent + 1 )
1295 (indent+1).times { print " " }
1296 puts "type:"
1297 @type.show_tree( indent + 2 )
1298 (indent+1).times { print " " }
1299 puts "subscript:"
1300 if @subscript then
1301 @subscript.show_tree( indent + 2 )
1302 else
1303 (indent+2).times { print " " }
1304 puts "no subscript"
1305 end
1306 end
1307end
1308
1309class PtrType < Type
1310# @type:: refer to : PtrType, FuncType, ArrayType, IntType, FloatType, ...
1311# @size:: Expr, or nil if not specified
1312# @count:: Expr, or nil if not specified
1313# @string:: Expr or -1(if size not specified) (string 引数), or nil if not specified
1314
1315 include HasType
1316
1317 def initialize( referto = nil )
1318 super()
1319 @type = referto
1320 @size = nil
1321 @count = nil
1322 @string = nil
1323 initHasType
1324 end
1325
1326 def set_type( type )
1327 unless @type then
1328 @type = type
1329 else
1330 @type.set_type( type ) # 枝先の type を設定
1331 end
1332 end
1333
1334 def get_type_str
1335 if @type.kind_of?( ArrayType ) || @type.kind_of?( FuncType ) then
1336 parenthes = "("
1337 else
1338 parenthes = ""
1339 end
1340 return "#{@type.get_type_str}#{parenthes}*"
1341 end
1342
1343 def get_type_str_post
1344 if @type.kind_of?( ArrayType ) || @type.kind_of?( FuncType ) then
1345 parenthes = ")"
1346 else
1347 parenthes = ""
1348 end
1349 "#{parenthes}#{@type.get_type_str_post}"
1350 end
1351
1352 def check # 意味的誤りがあれば、文字列を返す
1353 return nil if @type == nil
1354 @type.check
1355 end
1356
1357 def check_struct_tag kind
1358 if kind != :MEMBER # 構造体メンバーの場合、ポインタの先の構造体タグをチェックしない
1359 @type.check_struct_tag kind
1360 end
1361 end
1362
1363 def check_init( locale, ident, initializer, kind, attribute = nil )
1364 if ( initializer.instance_of?( Expression ) ) then
1365 val = initializer.eval_const2( nil, attribute )
1366 if val.kind_of? PointerVal then
1367 type = val.get_type # PtrType
1368 t1 = self
1369 t2 = type
1370 while( t1.kind_of?( PtrType ) && t2.kind_of?( PtrType ) )
1371 t1 = t1.get_type
1372 t2 = t2.get_type
1373 if ( t1.class == t2.class ) && ( t1.get_bit_size == t2.get_bit_size ) then
1374 elsif ( t1.kind_of?( CDefinedType) || t2.kind_of?( CDefinedType ) )&& t1.get_type_str == t2.get_type_str && t1.get_type_str_post && t2.get_type_str_post then
1375 # int8_t などが、一方は .h に定義されているケース
1376 else
1377 cdl_error2( locale, "T1032 $1: incompatible pointer type" , ident )
1378 break
1379 end
1380 end
1381 elsif val.kind_of? IntegerVal then
1382 if val.to_i != 0 then
1383 cdl_error2( locale, "T1033 $1: need cast to assign integer to pointer" , ident )
1384 end
1385 elsif val.kind_of? StringVal then
1386 # 文字列定数
1387 # mikan L"wide string"
1388 if @type.get_bit_size != -1 && @type.get_bit_size != -11 then # -1: char_t
1389 cdl_error2( locale, "T1034 $1: unsuitable string constant" , ident )
1390 end
1391 elsif ( val.instance_of?( Array ) ) then
1392 i = 0
1393 val.each { |ini|
1394 @type.check_init( locale, "#{ident}[#{i}]", ini, kind, attribute = nil )
1395 i += 1
1396 }
1397 elsif val.instance_of?( C_EXP ) then
1398
1399 else
1400 cdl_error2( locale, "T1035 $1: unsuitable initializer for pointer" , ident )
1401 end
1402 elsif ( initializer.instance_of?( Array ) ) then
1403 if @size == nil && @count == nil then
1404 cdl_error2( locale, "T9999 $1: non-size_is pointer cannot have array initializer", ident )
1405 end
1406
1407 i = 0
1408 initializer.each { |ini|
1409 @type.check_init( locale, "#{ident}[#{i}]", ini, kind, attribute = nil )
1410 i += 1
1411 }
1412 elsif( initializer.instance_of?( C_EXP ) ) then
1413
1414 else
1415 cdl_error2( locale, "T1036 $1: unsuitable initializer for pointer" , ident )
1416 end
1417 end
1418
1419 def get_referto
1420 clone_type
1421 @type
1422 end
1423
1424 def set_scs( size, count, string, max, b_nullable )
1425 @size = size
1426 @count = count
1427 @max = max
1428 @b_nullable = b_nullable
1429
1430 # string は最も左側の ptr に作用する
1431 if @type.kind_of?( PtrType ) then
1432 # ptr_level が 2 以上であることは ParamDecl#initializer でチェックされる
1433 clone_type
1434 @type.set_scs( nil, nil, string, nil, false )
1435 elsif @type.kind_of?( VoidType ) && ( size || count || string ) then
1436 str = ""
1437 if size then
1438 str = "size_is"
1439 end
1440 if count then
1441 if str then
1442 str += ", "
1443 end
1444 str += "count_is"
1445 end
1446 if string then
1447 if str then
1448 str += ", "
1449 end
1450 str += "string"
1451 end
1452
1453 cdl_error( "T1040 $1 specified for void pointer type", str )
1454 else
1455 @string = string
1456 end
1457
1458 if (@size != nil) && (@b_nullable != false) then
1459 cdl_error( "T9999 size_is & nullable cannot be specified simultaneously. If size is zero, pointer must be null")
1460 end
1461 end
1462
1463 def clear_max
1464 @max = nil
1465 end
1466
1467 def get_size
1468 @size
1469 end
1470
1471 def get_count
1472 @count
1473 end
1474
1475 def get_string
1476 @string
1477 end
1478
1479 #=== PtrType# size_is の最大値
1480 def get_max
1481 @max
1482 end
1483
1484 def is_nullable?
1485 return @b_nullable
1486 end
1487
1488 def get_type
1489 clone_type
1490 @type
1491 end
1492
1493 def has_pointer?
1494 true
1495 end
1496
1497 def has_sized_pointer?
1498 @size != nil || @count != nil || @string.instance_of?( Expression ) || @type.has_sized_pointer?
1499 end
1500
1501 def has_unsized_string?
1502 @string == -1 || @type.has_unsized_string?
1503 end
1504
1505 def show_tree( indent )
1506 indent.times { print " " }
1507 puts "PtrType: qualifier=#{@qualifier}, nullable=#{@b_nullable} #{locale_str}"
1508 super( indent + 1 )
1509 (indent+1).times { print " " }
1510 if @size then
1511 print "size=#{@size.to_s}, "
1512 else
1513 print "size=nil, "
1514 end
1515 if @max then
1516 print "max=#{@size.to_s}, "
1517 else
1518 print "max=nil, "
1519 end
1520 if @count then
1521 print "count=#{@count.to_s}, "
1522 else
1523 print "count=nil, "
1524 end
1525 if @string then
1526 if @string.instance_of?( Expression ) then
1527 print "string=#{@string.to_s}\n"
1528 else
1529 print "string=yes\n"
1530 end
1531 else
1532 print "string=nil\n"
1533 end
1534
1535 (indent+1).times { print " " }
1536 puts "type:"
1537 @type.show_tree( indent + 2 )
1538 end
1539
1540end
1541
1542#== DescriptorType クラス
1543# 動的結合で渡すデスクリプタ型
1544class DescriptorType < Type
1545# @sinagure_nsp::NamespacePath
1546
1547 def initialize( signature_nsp )
1548 @signature_nsp = signature_nsp
1549 obj = Namespace.find signature_nsp
1550 if ! obj.kind_of? Signature then
1551 cdl_error( "T9999 '$1': not signature or not found", signature_nsp.to_s )
1552 else
1553 if obj.has_descriptor? then
1554 cdl_error( "T9999 '$1': has Desicrptor in function parameter", signature_nsp.to_s )
1555 end
1556 end
1557 end
1558
1559 def get_type_str
1560 "Descriptor( #{@signature_nsp.to_s} )"
1561 end
1562
1563 def get_type_str_post
1564 ""
1565 end
1566
1567 def set_qualifier( qualifier )
1568 cdl_error( "T9999 '$1' cannot be specified for Descriptor", qualfier.to_s )
1569 end
1570
1571 def check
1572 end
1573
1574 def check_init( locale, ident, initializer, kind, attribute = nil )
1575 case kind
1576 when :PARAMETER
1577 # 引数は初期化できない
1578 else
1579 cdl_error2( locale, "T9999 Descriptor cannot be used for $1", kind)
1580 end
1581 end
1582
1583 #== DescriptorType#
1584 # 意味解析段階では nil が返される可能性に注意
1585 def get_signature
1586 Namespace.find @signature_nsp
1587 end
1588end
1589
1590# 以下単体テストコード
1591if $unit_test then
1592 puts( "===== Unit Test: IntType ===== (types.rb)")
1593 sizes = [ 8, 16, 32, 64 ]
1594 sizes.each{ |n|
1595 int = IntType.new n
1596 printf( "%8s max: %d min:%d\n", "int#{n}_t", int.get_max, int.get_min )
1597 }
1598 puts ""
1599end
Note: See TracBrowser for help on using the repository browser.