FreeBASIC  0.91.0
ast-node-data.bas
Go to the documentation of this file.
1 '' DATA stmt nodes (l = head; r = tail)
2 ''
3 '' chng: dec/2006 written [v1ctor]
4 
5 #include once "fb.bi"
6 #include once "fbint.bi"
7 #include once "ir.bi"
8 #include once "ast.bi"
9 
10 declare sub hCreateDataDesc( )
11 
13  ast.data.lastsym = NULL
14  ast.data.firstsym = NULL
15  ast.data.lastlbl = NULL
16 
17  '' assuming it's safe to call symb* from here (the desc must be
18  '' allocated at module-level or it would be removed if RESTORE
19  '' was used with a forward-label inside a proc)
21 end sub
22 
23 function astDataStmtBegin( ) as ASTNODE ptr
24  dim as ASTNODE ptr n = any
25 
26  '' alloc new node
27  n = astNewNode( AST_NODECLASS_DATASTMT, FB_DATATYPE_INVALID )
28 
29  n->data.elmts = 0
30 
31  function = n
32 end function
33 
34 function astDataStmtStore _
35  ( _
36  byval tree as ASTNODE ptr, _
37  byval expr as ASTNODE ptr _
38  ) as ASTNODE ptr
39 
40  dim as ASTNODE ptr n = any
41 
42  '' alloc new node
43  n = astNewNode( AST_NODECLASS_DATASTMT, FB_DATATYPE_INVALID )
44 
45  n->l = expr
46  n->r = NULL
47 
48  if( tree->l = NULL ) then
49  tree->l = n
50  else
51  tree->r->r = n
52  end if
53 
54  tree->r = n
55 
56  '' check type
57  if( expr = NULL ) then
58  n->data.id = FB_DATASTMT_ID_LINK
59 
60  else
61  dim as FBSYMBOL ptr litsym = any
62 
63  select case astGetDataType( expr )
64  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
65  litsym = astGetStrLitSymbol( expr )
66  case else
67  litsym = NULL
68  end select
69 
70  '' string?
71  if( litsym <> NULL ) then
72  '' not a wstring?
73  if( astGetDataType( expr ) <> FB_DATATYPE_WCHAR ) then
74  n->data.id = FB_DATASTMT_ID_ZSTR
75  '' wstring..
76  else
77  n->data.id = FB_DATASTMT_ID_WSTR
78  end if
79 
80  '' scalar..
81  else
82  '' address of?
83  if( astIsOFFSET( expr ) ) then
84  n->data.id = FB_DATASTMT_ID_OFFSET
85  else
86  n->data.id = FB_DATASTMT_ID_CONST
87  end if
88  end if
89  end if
90 
91  tree->data.elmts += 1
92 
93  function = n
94 
95 end function
96 
97 sub astDataStmtEnd( byval tree as ASTNODE ptr )
98 
99  dim as FBSYMBOL ptr array = any, elm = any
100  dim as integer i = any, id = any
101  dim as ASTNODE ptr n = any, expr = any, initree = any
102  dim as string littext
103 
104  '' add the last node: the link
105  astDataStmtStore( tree, NULL )
106 
107  '' create/lookup the datadesc array symbol for the last symbol
108 
109  array = astDataStmtAdd( NULL, tree->data.elmts )
110 
111  '' initialize it
112  initree = astTypeIniBegin( FB_DATATYPE_STRUCT, ast.data.desc, TRUE )
113 
114  astTypeIniScopeBegin( initree, NULL )
115 
116  '' for each node..
117  n = tree->l
118  for i = 0 to tree->data.elmts - 1
119  id = n->data.id
120  expr = n->l
121 
122  astTypeIniScopeBegin( initree, NULL )
123 
124  select case n->data.id
125  case FB_DATASTMT_ID_ZSTR
126  id = symbGetStrLen( astGetStrLitSymbol( expr ) ) - 1
127  expr = astNewADDROF( expr )
128 
129  case FB_DATASTMT_ID_WSTR
130  id = FB_DATASTMT_ID_WSTR + _
131  (symbGetWstrLen( astGetStrLitSymbol( expr ) ) - 1)
132  expr = astNewADDROF( expr )
133 
134  case FB_DATASTMT_ID_CONST
135  littext = astConstFlushToStr( expr )
136  id = len( littext )
137  expr = astNewADDROF( astNewCONSTstr( littext ) )
138 
139  case FB_DATASTMT_ID_NULL, FB_DATASTMT_ID_LINK
140  expr = astNewCONSTi( 0 )
141 
142  end select
143 
144  '' .id = id
145  elm = symbGetUDTSymbTbHead( ast.data.desc )
146  astTypeIniAddAssign( initree, _
147  astNewCONSTi( id, FB_DATATYPE_SHORT ), _
148  elm )
149 
150  elm = symbGetNext( elm )
151 
152  '' .node = expr
153  astTypeIniAddAssign( initree, expr, elm )
154 
155  astTypeIniScopeEnd( initree, NULL )
156 
157  '' next
158  dim as ASTNODE ptr nxt = n->r
159  astDelNode( n )
160  n = nxt
161  next
162 
163  ''
164  astTypeIniScopeEnd( initree, NULL )
165 
166  astTypeIniEnd( initree, TRUE )
167 
168  symbSetTypeIniTree( array, initree )
169  symbSetIsInitialized( array )
170 
171  '' Link the previous DATA stmt to this new one
172  if( ast.data.lastsym <> NULL ) then
173  '' lastarray(ubound(lastarray)).next = @array(0)
174  initree = symbGetTypeIniTree( astGetLastDataStmtSymbol( ) )
175 
176  n = initree->l
177  var tn = n
178  do while( n->r <> NULL )
179  if( n->class = AST_NODECLASS_TYPEINI_ASSIGN ) then
180  tn = n
181  end if
182  n = n->r
183  loop
184 
185  '' del the NULL expr
186  astDelNode( tn->l )
187 
188  '' replace the node
189  tn->l = astNewADDROF( astNewVAR( array ) )
190  end if
191 
192  '' datadesc arrays can reference the next datadesc array (link to next
193  '' DATA stmt as patched in above) or previous ones (those that were
194  '' pre-declared for RESTORE <label>).
195  '' For the C backend we must set up a reverse linked list allowing it to
196  '' cleanly emit the datadesc arrays without running into declaration
197  '' order issues.
198  array->var_.data.prev = ast.data.lastsym
199 
200  ast.data.lastsym = array
201  if( ast.data.firstsym = NULL ) then
202  ast.data.firstsym = array
203  end if
204 
205 end sub
206 
207 function astDataStmtAdd _
208  ( _
209  byval label as FBSYMBOL ptr, _
210  byval elements as integer _
211  ) as FBSYMBOL ptr
212 
213  static as string id
214  static as FBARRAYDIM dTB(0 to 0)
215  dim as FBSYMBOL ptr sym = any, lastlabel = any
216 
217  if( label = NULL ) then
218  '' Called for DATA statement end, or RESTORE without label
219  '' Create the static datadesc array
220  lastlabel = symbGetLastLabel( )
221 
222  if( (lastlabel = NULL) or (ast.data.lastlbl = lastlabel) ) then
223  '' no label at all/still under the same label
224  id = *symbUniqueLabel( )
225  else
226  ast.data.lastlbl = lastlabel
227 
228  '' static datadesc array id specifically for that label
229  '' (it may be looked up by RESTORE later, see below)
230  id = FB_DATASTMT_PREFIX + *symbGetName( lastlabel )
231  end if
232 
233  dTB(0).upper = elements - 1
234  else
235  '' Called for RESTORE <label>
236  '' static datadesc array id specifically for that label
237  '' (if <label> is a forward reference, then this datadesc array
238  '' may be looked up by astDataStmtEnd() later,
239  '' when the corresponding DATA is found)
240  id = FB_DATASTMT_PREFIX + *symbGetName( label )
241  dTB(0).upper = 0
242  end if
243 
244  sym = symbLookupByNameAndClass( @symbGetGlobalNamespc( ), id, FB_SYMBCLASS_VAR, TRUE, FALSE )
245 
246  '' already declared?
247  if( sym <> NULL ) then
248  if( label = NULL ) then
249  '' reset the array dimensions
250  symbSetArrayDimTb( sym, 1, dTB() )
251  end if
252  return sym
253  end if
254 
255  sym = symbAddVar( id, symbUniqueLabel( ), _
256  FB_DATATYPE_STRUCT, ast.data.desc, 0, _
257  1, dTB(), _
258  FB_SYMBATTRIB_SHARED or FB_SYMBATTRIB_STATIC, _
259  FB_SYMBOPT_MOVETOGLOB or FB_SYMBOPT_PRESERVECASE )
260 
261  '' (set by astDataStmtEnd())
262  sym->var_.data.prev = NULL
263 
264  function = sym
265 end function
266 
268  static as FBARRAYDIM dTB(0)
269 
270  '' Using FIELD = 1, to pack it as done by the rtlib
271  ast.data.desc = symbStructBegin( NULL, NULL, "__FB_DATADESC$", NULL, FALSE, 1, NULL, 0 )
272 
273  '' type as short
274  symbAddField( ast.data.desc, "type", 0, dTB(), _
275  FB_DATATYPE_SHORT, NULL, 0, 0 )
276 
277  '' node as FB_DATASTMT_NODE (no need to create an UNION, all fields are pointers)
278  symbAddField( ast.data.desc, "node", 0, dTB(), _
279  typeAddrOf( FB_DATATYPE_VOID ), NULL, 0, 0 )
280 
281  symbStructEnd( ast.data.desc )
282 end sub
283