FreeBASIC  0.91.0
parser-quirk-casting.bas
Go to the documentation of this file.
1 '' quirk casting functions (CBYTE, CSHORT, CINT, ...) parsing
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "parser.bi"
9 #include once "ast.bi"
10 
11 '':::::
12 ''TypeConvExpr = (C### '(' expression ')') .
13 ''
14 function cTypeConvExpr _
15  ( _
16  byval tk as FB_TOKEN, _
17  byval isASM as integer = FALSE _
18  ) as ASTNODE ptr
19 
20  dim as integer dtype = any, op = any, errmsg = any
21  dim as ASTNODE ptr expr = any
22 
23  dtype = FB_DATATYPE_INVALID
24  op = INVALID
25 
26  select case as const tk
27  case FB_TK_CBYTE
28  dtype = FB_DATATYPE_BYTE
29 
30  case FB_TK_CUBYTE
31  dtype = FB_DATATYPE_UBYTE
32 
33  case FB_TK_CSHORT
34  dtype = FB_DATATYPE_SHORT
35 
36  case FB_TK_CUSHORT
37  dtype = FB_DATATYPE_USHORT
38 
39  case FB_TK_CINT
40  dtype = env.lang.integerkeyworddtype
41 
42  case FB_TK_CUINT
43  dtype = FB_DATATYPE_UINT
44 
45  case FB_TK_CLNG
46  dtype = FB_DATATYPE_LONG
47 
48  case FB_TK_CULNG
49  dtype = FB_DATATYPE_ULONG
50 
51  case FB_TK_CLNGINT
52  dtype = FB_DATATYPE_LONGINT
53 
54  case FB_TK_CULNGINT
55  dtype = FB_DATATYPE_ULONGINT
56 
57  case FB_TK_CSNG
58  dtype = FB_DATATYPE_SINGLE
59 
60  case FB_TK_CDBL
61  dtype = FB_DATATYPE_DOUBLE
62 
63  case FB_TK_CSIGN
64  op = AST_OP_TOSIGNED
65 
66  case FB_TK_CUNSG
67  op = AST_OP_TOUNSIGNED
68 
69  end select
70 
71  if( dtype = FB_DATATYPE_INVALID ) then
72  if( op = INVALID ) then
73  return NULL
74  end if
75  end if
76 
77  lexSkipToken( )
78 
79  if( (tk = FB_TK_CINT) or (tk = FB_TK_CUINT) ) then
80 
81  '' ['<' lgt '>']
82  if( hMatch( FB_TK_LT ) ) then
83 
84  '' expr
85  var lgt = cConstIntExpr( cGtInParensOnlyExpr( ) )
86 
87  dtype = hIntegerTypeFromBitSize( lgt, (tk = FB_TK_CUINT) )
88 
89  if( hMatch( FB_TK_GT ) = FALSE ) then
90  errReport( FB_ERRMSG_EXPECTEDGT )
91  end if
92 
93  end if
94 
95  end if
96 
97  '' '('
98  if( hMatch( CHAR_LPRNT ) = FALSE ) then
99  errReport( FB_ERRMSG_EXPECTEDLPRNT )
100  end if
101 
102  expr = cExpression( )
103  if( expr = NULL ) then
104  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
105  expr = astNewCONSTi( 0 )
106  end if
107 
108  select case op
109  case AST_OP_TOSIGNED
110  dtype = typeToSigned( astGetFullType( expr ) )
111  case AST_OP_TOUNSIGNED
112  dtype = typeToUnsigned( astGetFullType( expr ) )
113  end select
114 
115  expr = astNewCONV( dtype, NULL, expr, AST_CONVOPT_CHECKSTR, @errmsg )
116  if( expr = NULL ) then
117  if( errmsg = FB_ERRMSG_OK ) then
118  errmsg = FB_ERRMSG_TYPEMISMATCH
119  end if
120  errReport( errmsg, TRUE )
121 
122  expr = astNewCONSTi( 0 )
123  end if
124 
125  '' ')'
126  if( lexGetToken( ) <> CHAR_RPRNT ) then
127  errReport( FB_ERRMSG_EXPECTEDRPRNT )
128  hSkipUntil( CHAR_RPRNT, TRUE )
129  else
130  if isASM = FALSE then
131  lexSkipToken( )
132  end if
133  end if
134 
135  function = expr
136 
137 end function
138 
139 '' AnonType = TYPE ('<' SymbolType '>')? '(' ... ')'
140 function cAnonType( ) as ASTNODE ptr
141  dim as ASTNODE ptr initree = any
142  dim as FBSYMBOL ptr sym = any, subtype = any
143  dim as integer dtype = any, is_explicit = any
144 
145  '' TYPE
146  lexSkipToken( )
147 
148  '' '<'?
149  is_explicit = hMatch( FB_TK_LT )
150 
151  if( is_explicit ) then
152  '' SymbolType
153  if( cSymbolType( dtype, subtype, 0 ) = FALSE ) then
154  '' it would be nice to be able to fall back and do
155  '' a cExpression(), like typeof(), or len() do,
156  '' however the ambiguity with the "greater-than '>' operator"
157  '' and the "type<foo'>'(bar)"....
158  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
159  '' error recovery: fake a type
160  dtype = FB_DATATYPE_INTEGER
161  subtype = NULL
162  end if
163  else
164  '' use the type from the left-hand expression,
165  '' this allows totally anonymous types.
166  subtype = parser.ctxsym
167  dtype = parser.ctx_dtype
168 
169  if( dtype = FB_DATATYPE_INVALID ) then
170  errReport( FB_ERRMSG_INCOMPLETETYPE )
171  dtype = FB_DATATYPE_INTEGER
172  subtype = NULL
173  end if
174 
175  select case( typeGetDtAndPtrOnly( dtype ) )
176  case FB_DATATYPE_VOID, FB_DATATYPE_FWDREF
177  errReport( FB_ERRMSG_INCOMPLETETYPE )
178  dtype = FB_DATATYPE_INTEGER
179  subtype = NULL
180  end select
181  end if
182 
183  '' Disallow creating objects of abstract classes
184  hComplainIfAbstractClass( dtype, subtype )
185 
186  if( is_explicit ) then
187  '' '>'
188  if( hMatch( FB_TK_GT ) = FALSE ) then
189  errReport( FB_ERRMSG_SYNTAXERROR )
190  '' error recovery: skip until next '>'
191  hSkipUntil( FB_TK_GT, TRUE )
192  end if
193  end if
194 
195  '' UDT?
196  if( typeGetDtAndPtrOnly( dtype ) = FB_DATATYPE_STRUCT ) then
197  '' Has a ctor?
198  if( symbGetCompCtorHead( subtype ) ) then
199  initree = cCtorCall( subtype )
200  if( initree = NULL ) then
201  '' Error recovery
202  initree = astNewCONSTz( dtype, subtype )
203  end if
204  return initree
205  end if
206  end if
207 
208  '' Use temp var so the rest can be parsed as var initializer,
209  '' then delete the temp var again, similar to astCALLCTORToCALL()
210  sym = symbAddTempVar( dtype, subtype )
211  initree = cInitializer( sym, FB_INIOPT_NONE )
212  astReplaceSymbolOnTree( initree, sym, NULL )
213  symbDelSymbol( sym )
214 
215  '' This gives us a clean TYPEINI tree (like a parameter initializer),
216  '' allowing astNewASSIGN() to optimize it by initializing the lhs
217  '' directly instead of using a temp var, and if that does not happen,
218  '' then astTypeIniUpdate() will take care of it.
219 
220  function = initree
221 end function
222