Skip to content

Commit 92ff3d0

Browse files
committed
Extend multivarinit to typed constants
const a, b, c: integer = 42; const r1, r2: TRec = (field: value); Name list is collected before the colon, then each symbol is created and initialized via token record/replay.
1 parent d043380 commit 92ff3d0

1 file changed

Lines changed: 76 additions & 27 deletions

File tree

compiler/pdecl.pas

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -237,20 +237,41 @@ implementation
237237
skip_initialiser : boolean;
238238
varspez : tvarspez;
239239
asmtype : tasmlisttype;
240+
names : array of TIDString;
241+
positions : array of tfileposinfo;
242+
syms : array of tsym;
243+
namecount,ni : longint;
244+
tokenbuf : tdynamicarray;
245+
already_recording : boolean;
240246
begin
241247
old_block_type:=block_type;
242248
block_type:=bt_const;
243249
had_generic:=false;
244250
first:=true;
245251
repeat
246-
orgname:=current_scanner.orgpattern;
247-
filepos:=current_tokenpos;
248-
isgeneric:=not (m_delphi in current_settings.modeswitches) and (current_scanner.token=_ID) and (current_scanner.idtoken=_GENERIC);
249-
consume(_ID);
252+
{ collect one or more names separated by commas }
253+
namecount:=0;
254+
names:=nil;
255+
positions:=nil;
256+
syms:=nil;
257+
repeat
258+
setlength(names,namecount+1);
259+
setlength(positions,namecount+1);
260+
names[namecount]:=current_scanner.orgpattern;
261+
positions[namecount]:=current_tokenpos;
262+
inc(namecount);
263+
consume(_ID);
264+
until not((m_multi_var_init in current_settings.modeswitches) and
265+
try_to_consume(_COMMA));
266+
orgname:=names[0];
267+
filepos:=positions[0];
268+
isgeneric:=not (m_delphi in current_settings.modeswitches) and (namecount=1) and (current_scanner.idtoken=_GENERIC);
250269
case current_scanner.token of
251270

252271
_EQ:
253272
begin
273+
if namecount>1 then
274+
Message(parser_e_initialized_only_one_var);
254275
consume(_EQ);
255276
sym:=readconstant(orgname,filepos,nodetype);
256277
{ Support hint directives }
@@ -294,9 +315,6 @@ implementation
294315
consume(_COLON);
295316
read_anon_type(hdef,false,nil);
296317
block_type:=bt_const;
297-
{ create symbol }
298-
storetokenpos:=current_tokenpos;
299-
current_tokenpos:=filepos;
300318
if not (cs_typed_const_writable in current_settings.localswitches) then
301319
begin
302320
varspez:=vs_const;
@@ -307,26 +325,34 @@ implementation
307325
varspez:=vs_value;
308326
asmtype:=al_typedconsts;
309327
end;
310-
{ if we are dealing with structure const then we need to handle it as a
311-
structure static variable: create a symbol in unit symtable and a reference
312-
to it from the structure or linking will fail }
313-
if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
328+
{ create symbol(s) }
329+
setlength(syms,namecount);
330+
for ni:=0 to namecount-1 do
314331
begin
315-
{ note: we keep hdef so that we might at least read the
316-
constant data correctly for error recovery }
317-
check_allowed_for_var_or_const(hdef,false);
318-
sym:=cfieldvarsym.create(orgname,varspez,hdef,[]);
319-
symtablestack.top.insertsym(sym);
320-
sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));
321-
end
322-
else
323-
begin
324-
sym:=cstaticvarsym.create(orgname,varspez,hdef,[]);
325-
sym.visibility:=symtablestack.top.currentvisibility;
326-
symtablestack.top.insertsym(sym);
332+
storetokenpos:=current_tokenpos;
333+
current_tokenpos:=positions[ni];
334+
{ if we are dealing with structure const then we need to handle it as a
335+
structure static variable: create a symbol in unit symtable and a reference
336+
to it from the structure or linking will fail }
337+
if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
338+
begin
339+
{ note: we keep hdef so that we might at least read the
340+
constant data correctly for error recovery }
341+
check_allowed_for_var_or_const(hdef,false);
342+
syms[ni]:=cfieldvarsym.create(names[ni],varspez,hdef,[]);
343+
symtablestack.top.insertsym(syms[ni]);
344+
syms[ni]:=make_field_static(symtablestack.top,tfieldvarsym(syms[ni]));
345+
end
346+
else
347+
begin
348+
syms[ni]:=cstaticvarsym.create(names[ni],varspez,hdef,[]);
349+
syms[ni].visibility:=symtablestack.top.currentvisibility;
350+
symtablestack.top.insertsym(syms[ni]);
351+
end;
352+
syms[ni].register_sym;
353+
current_tokenpos:=storetokenpos;
327354
end;
328-
sym.register_sym;
329-
current_tokenpos:=storetokenpos;
355+
sym:=syms[0];
330356
skip_initialiser:=false;
331357
{ Anonymous proctype definitions can have proc directives }
332358
if (
@@ -355,8 +381,31 @@ implementation
355381
if not skip_initialiser then
356382
begin
357383
consume(_EQ);
358-
maybe_guarantee_record_typesym(tstaticvarsym(sym).vardef,tstaticvarsym(sym).vardef.owner);
359-
read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(sym),in_structure);
384+
if namecount=1 then
385+
begin
386+
maybe_guarantee_record_typesym(tstaticvarsym(sym).vardef,tstaticvarsym(sym).vardef.owner);
387+
read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(sym),in_structure);
388+
end
389+
else
390+
begin
391+
{ record tokens for replay }
392+
already_recording:=current_scanner.is_recording_tokens;
393+
tokenbuf:=tdynamicarray.create(256);
394+
if not already_recording then
395+
current_scanner.startrecordtokens(tokenbuf);
396+
maybe_guarantee_record_typesym(tstaticvarsym(sym).vardef,tstaticvarsym(sym).vardef.owner);
397+
read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(sym),in_structure);
398+
if not already_recording then
399+
current_scanner.stoprecordtokens;
400+
for ni:=1 to namecount-1 do
401+
begin
402+
maybe_guarantee_record_typesym(tstaticvarsym(syms[ni]).vardef,tstaticvarsym(syms[ni]).vardef.owner);
403+
tokenbuf.seek(0);
404+
current_scanner.startreplaytokens(tokenbuf,false);
405+
read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(syms[ni]),in_structure);
406+
end;
407+
tokenbuf.free;
408+
end;
360409
end;
361410
end;
362411

0 commit comments

Comments
 (0)