* Introduce m_processed

This commit is contained in:
Michaël Van Canneyt 2024-02-07 17:11:47 +01:00 committed by Michael Van Canneyt
parent 5298e25c84
commit 462c201ce6
4 changed files with 169 additions and 113 deletions

View File

@ -57,9 +57,12 @@ type
public public
constructor create; constructor create;
destructor destroy; override; destructor destroy; override;
// Find the task for module m
function findtask(m : tmodule) : ttask_list; function findtask(m : tmodule) : ttask_list;
// Can we continue processing this module ? // Can we continue processing this module ? If not, firstwaiting contains first module that m is waiting for.
function cancontinue(t : ttask_list) : boolean; function cancontinue(m : tmodule; checksub : boolean; out firstwaiting: tmodule): boolean;
// Overload of cancontinue, based on task.
function cancontinue(t: ttask_list; out firstwaiting: tmodule): boolean; inline
// Continue processing this module. Return true if the module is done and can be removed. // Continue processing this module. Return true if the module is done and can be removed.
function continue(t : ttask_list): Boolean; function continue(t : ttask_list): Boolean;
// process the queue. Note that while processing the queue, elements will be added. // process the queue. Note that while processing the queue, elements will be added.
@ -77,7 +80,7 @@ procedure DoneTaskHandler;
implementation implementation
uses verbose, finput, globtype, sysutils, scanner, parser, pmodules; uses verbose, fppu, finput, globtype, sysutils, scanner, parser, pmodules;
procedure InitTaskHandler; procedure InitTaskHandler;
begin begin
@ -126,22 +129,21 @@ end;
procedure ttask_list.SaveState; procedure ttask_list.SaveState;
begin begin
if State=Nil then if State=Nil then
State:=tglobalstate.Create(true); State:=tglobalstate.Create(true)
else
State.save(true);
end; end;
procedure ttask_list.RestoreState; procedure ttask_list.RestoreState;
begin begin
if not module.is_reset then if not module.is_reset then
state.restore(true); state.restore(true);
if assigned(current_scanner) and assigned(current_scanner.inputfile) then if assigned(current_scanner) and assigned(current_scanner.inputfile) then
if current_scanner.inputfile.closed then if current_scanner.inputfile.closed then
begin begin
current_scanner.tempopeninputfile; current_scanner.tempopeninputfile;
current_scanner.gettokenpos; current_scanner.gettokenpos;
// parser_current_file:=current_scanner.inputfile.name;
end; end;
end; end;
{ ttask_handler } { ttask_handler }
@ -172,25 +174,63 @@ begin
end; end;
end; end;
function ttask_handler.cancontinue(t : ttask_list): boolean; function ttask_handler.cancontinue(m: tmodule; checksub : boolean; out firstwaiting: tmodule): boolean;
procedure CheckUsed(out acandidate : tmodule);
var
itm : TLinkedListItem;
iscandidate : boolean;
m2 : tmodule;
begin
acandidate:=nil;
itm:=m.used_units.First;
while (acandidate=Nil) and assigned(itm) do
begin
iscandidate:=Not (tused_unit(itm).u.state in [ms_compiled]);
if iscandidate then
begin
acandidate:=tused_unit(itm).u;
if not cancontinue(acandidate,false,m2) then
acandidate:=nil;
end;
itm:=itm.Next;
end;
end;
var var
m : tmodule; m2 : tmodule;
begin begin
m:=t.module; firstwaiting:=nil;
if m.is_initial and (list.count>1) then
exit(False);
case m.state of case m.state of
ms_unknown : cancontinue:=true; ms_unknown : cancontinue:=true;
ms_registered : cancontinue:=true; ms_registered : cancontinue:=true;
ms_compile : cancontinue:=true; ms_compile : cancontinue:=true;
ms_compiling_waitimpl : cancontinue:=m.usedunitsloaded(false); ms_compiling_waitimpl : cancontinue:=m.usedunitsloaded(false,firstwaiting);
ms_compiling_waitintf : cancontinue:=m.usedunitsloaded(true); ms_compiling_waitintf : cancontinue:=m.usedunitsloaded(true,firstwaiting);
ms_compiling_wait : cancontinue:=m.usedunitsloaded(true); ms_compiling_wait : cancontinue:=m.usedunitsloaded(true,firstwaiting);
ms_compiled : cancontinue:=true; ms_compiled : cancontinue:=true;
ms_processed : cancontinue:=true;
ms_moduleerror : cancontinue:=true; ms_moduleerror : cancontinue:=true;
else else
InternalError(2024011802); InternalError(2024011802);
end; end;
if (not cancontinue) and checksub then
begin
checkused(m2);
if m2<>nil then
firstwaiting:=m2;
end;
end;
function ttask_handler.cancontinue(t : ttask_list; out firstwaiting : tmodule): boolean;
begin
Result:=cancontinue(t.module,true,firstwaiting);
end; end;
function ttask_handler.continue(t : ttask_list) : Boolean; function ttask_handler.continue(t : ttask_list) : Boolean;
@ -205,14 +245,23 @@ begin
case m.state of case m.state of
ms_registered : parser.compile_module(m); ms_registered : parser.compile_module(m);
ms_compile : parser.compile_module(m); ms_compile : parser.compile_module(m);
ms_compiled : if (not m.is_initial) or m.is_unit then
(m as tppumodule).post_load_or_compile(m.compilecount>1);
ms_compiling_waitintf : pmodules.parse_unit_interface_declarations(m); ms_compiling_waitintf : pmodules.parse_unit_interface_declarations(m);
ms_compiling_waitimpl : pmodules.proc_unit_implementation(m); ms_compiling_waitimpl : pmodules.proc_unit_implementation(m);
ms_compiling_wait : pmodules.proc_program_declarations(m,m.islibrary); ms_compiling_wait : pmodules.proc_program_declarations(m,m.islibrary);
ms_processed : ;
else else
InternalError(2024011801); InternalError(2024011801);
end; end;
Result:=m.state=ms_compiled; if m.state=ms_compiled then
if not Result then begin
parsing_done(m);
if m.is_initial and not m.is_unit then
m.state:=ms_processed;
end;
Result:=m.state=ms_processed;
if not result then
// Not done, save state // Not done, save state
t.SaveState; t.SaveState;
end; end;
@ -220,14 +269,15 @@ end;
procedure ttask_handler.processqueue; procedure ttask_handler.processqueue;
var var
t : ttask_list; t,t2 : ttask_list;
process : boolean; process : boolean;
m,firstwaiting : tmodule;
begin begin
t:=list.firsttask; t:=list.firsttask;
While t<>nil do While t<>nil do
begin begin
process:=cancontinue(t); process:=cancontinue(t,firstwaiting);
if process then if process then
begin begin
if continue(t) then if continue(t) then
@ -238,14 +288,22 @@ begin
// maybe the strategy can be improved. // maybe the strategy can be improved.
t:=list.firsttask; t:=list.firsttask;
end end
else if assigned(firstwaiting) and cancontinue(firstwaiting,true, m) then
begin
t2:=findtask(firstwaiting);
if t2=nil then
t2:=t.nexttask;
t:=t2;
end
else else
begin
t:=t.nexttask; t:=t.nexttask;
end; end;
end;
end; end;
procedure ttask_handler.addmodule(m: tmodule); procedure ttask_handler.addmodule(m: tmodule);
var var
n : TSymStr; n : TSymStr;
e : tmodule; e : tmodule;
@ -265,7 +323,6 @@ begin
else else
begin begin
// We have a task, if it was reset, then clear the state and move the task to the start. // We have a task, if it was reset, then clear the state and move the task to the start.
if m.is_reset then if m.is_reset then
begin begin
m.is_reset:=false; m.is_reset:=false;

View File

@ -123,8 +123,11 @@ interface
ms_compiling_waitimpl, ms_compiling_waitimpl,
ms_compiling_wait, ms_compiling_wait,
ms_compiled, ms_compiled,
ms_processed,
ms_moduleerror ms_moduleerror
); );
tmodulestates = set of tmodulestate;
const const
ModuleStateStr : array[TModuleState] of string[32] = ( ModuleStateStr : array[TModuleState] of string[32] = (
'Unknown', 'Unknown',
@ -135,6 +138,7 @@ interface
'Compiling_Waiting_implementation', 'Compiling_Waiting_implementation',
'Compiling_Waiting', 'Compiling_Waiting',
'Compiled', 'Compiled',
'Processed',
'Error' 'Error'
); );

View File

@ -30,8 +30,9 @@ uses fmodule;
{$ifdef PREPROCWRITE} {$ifdef PREPROCWRITE}
procedure preprocess(const filename:string); procedure preprocess(const filename:string);
{$endif PREPROCWRITE} {$endif PREPROCWRITE}
procedure compile(const filename:string); function compile(const filename:string) : boolean;
procedure compile_module(module : tmodule); function compile_module(module : tmodule) : boolean;
procedure parsing_done(module : tmodule);
procedure initparser; procedure initparser;
procedure doneparser; procedure doneparser;
@ -54,6 +55,71 @@ implementation
pbase,psystem,pmodules,psub,ncgrtti, pbase,psystem,pmodules,psub,ncgrtti,
cpuinfo,procinfo; cpuinfo,procinfo;
procedure parsing_done(module: tmodule);
var
hp,hp2 : tmodule;
begin
module.end_of_parsing;
if (module.is_initial) and
(status.errorcount=0) then
{ Write Browser Collections }
do_extractsymbolinfo;
// olddata.restore(false);
{ Restore all locally modified warning messages }
RestoreLocalVerbosity(current_settings.pmessage);
current_exceptblock:=0;
exceptblockcounter:=0;
{ Shut down things when the last file is compiled succesfull }
if (module.is_initial) and (module.state=ms_compiled) and
(status.errorcount=0) then
begin
parser_current_file:='';
{ Close script }
if (not AsmRes.Empty) then
begin
Message1(exec_i_closing_script,AsmRes.Fn);
AsmRes.WriteToDisk;
end;
end;
{ free now what we did not free earlier in
proc_program PM }
if (module.is_initial) and (module.state=ms_compiled) and needsymbolinfo then
begin
hp:=tmodule(loaded_units.first);
while assigned(hp) do
begin
hp2:=tmodule(hp.next);
if (hp<>module) then
begin
loaded_units.remove(hp);
hp.free;
end;
hp:=hp2;
end;
{ free also unneeded units we didn't free before }
unloaded_units.Clear;
end;
{ If used units are compiled current_module is already the same as
the stored module. Now if the unit is not finished its scanner is
not yet freed and thus set_current_module would reopen the scanned
file which will result in pointing to the wrong position in the
file. In the normal case current_scanner and current_module.scanner
would be Nil, thus nothing bad would happen }
{ if olddata.old_current_module<>current_module then
set_current_module(olddata.old_current_module);}
FreeLocalVerbosity(current_settings.pmessage);
end;
procedure initparser; procedure initparser;
begin begin
@ -321,27 +387,26 @@ implementation
Compile a source file Compile a source file
*****************************************************************************} *****************************************************************************}
procedure compile(const filename:string); function compile(const filename:string) : boolean;
var var
m : TModule; m : TModule;
begin begin
m:=tppumodule.create(nil,'',filename,false); m:=tppumodule.create(nil,'',filename,false);
// m.is_initial:=initial;
m.state:=ms_compile; m.state:=ms_compile;
compile_module(m); result:=compile_module(m);
end; end;
procedure compile_module(module : tmodule); function compile_module(module : tmodule) : boolean;
var var
olddata : tglobalstate;
hp,hp2 : tmodule; hp,hp2 : tmodule;
finished : boolean; finished : boolean;
sc : tscannerfile; sc : tscannerfile;
begin begin
Result:=True;
{ parsing a procedure or declaration should be finished } { parsing a procedure or declaration should be finished }
if assigned(current_procinfo) then if assigned(current_procinfo) then
internalerror(200811121); internalerror(200811121);
@ -354,7 +419,6 @@ implementation
recursively } recursively }
{ handle the postponed case first } { handle the postponed case first }
flushpendingswitchesstate; flushpendingswitchesstate;
olddata:=tglobalstate.create(false);
{ reset parser, a previous fatal error could have left these variables in an unreliable state, this is { reset parser, a previous fatal error could have left these variables in an unreliable state, this is
important for the IDE } important for the IDE }
@ -431,10 +495,10 @@ implementation
else if (token=_ID) and (idtoken=_PACKAGE) then else if (token=_ID) and (idtoken=_PACKAGE) then
begin begin
module.IsPackage:=true; module.IsPackage:=true;
proc_package(module); finished:=proc_package(module);
end end
else else
proc_program(module,token=_LIBRARY); finished:=proc_program(module,token=_LIBRARY);
except except
on ECompilerAbort do on ECompilerAbort do
raise; raise;
@ -451,83 +515,14 @@ implementation
raise; raise;
end; end;
end; end;
Result:=Finished;
{ the program or the unit at the command line should not need to wait { the program or the unit at the command line should not need to wait
for other units } for other units }
if (module.is_initial) and not finished then // if (module.is_initial) and not finished then
internalerror(2012091901); // internalerror(2012091901);
finally finally
if assigned(module) then
begin
if finished then if finished then
module.end_of_parsing parsing_done(module);
else
begin
{ these are saved in the unit's state and thus can be set to
Nil again as would be done by tmodule.end_of_parsing }
macrosymtablestack:=nil;
symtablestack:=nil;
if current_scanner=current_module.scanner then
set_current_scanner(nil);
end;
end;
if (module.is_initial) and
(status.errorcount=0) then
{ Write Browser Collections }
do_extractsymbolinfo;
olddata.restore(false);
{ Restore all locally modified warning messages }
RestoreLocalVerbosity(current_settings.pmessage);
current_exceptblock:=0;
exceptblockcounter:=0;
{ Shut down things when the last file is compiled succesfull }
if (module.is_initial) and
(status.errorcount=0) then
begin
parser_current_file:='';
{ Close script }
if (not AsmRes.Empty) then
begin
Message1(exec_i_closing_script,AsmRes.Fn);
AsmRes.WriteToDisk;
end;
end;
{ free now what we did not free earlier in
proc_program PM }
if (module.is_initial) and needsymbolinfo then
begin
hp:=tmodule(loaded_units.first);
while assigned(hp) do
begin
hp2:=tmodule(hp.next);
if (hp<>module) then
begin
loaded_units.remove(hp);
hp.free;
end;
hp:=hp2;
end;
{ free also unneeded units we didn't free before }
unloaded_units.Clear;
end;
{ If used units are compiled current_module is already the same as
the stored module. Now if the unit is not finished its scanner is
not yet freed and thus set_current_module would reopen the scanned
file which will result in pointing to the wrong position in the
file. In the normal case current_scanner and current_module.scanner
would be Nil, thus nothing bad would happen }
if olddata.old_current_module<>current_module then
set_current_module(olddata.old_current_module);
FreeLocalVerbosity(current_settings.pmessage);
FreeAndNil(olddata);
end; end;
end; end;

View File

@ -3029,7 +3029,7 @@ type
if assigned(onfreescanner) then if assigned(onfreescanner) then
onfreescanner(self); onfreescanner(self);
if assigned(current_module) and if assigned(current_module) and
(current_module.state=ms_compiled) and (current_module.state in [ms_processed,ms_compiled]) and
(status.errorcount=0) then (status.errorcount=0) then
checkpreprocstack checkpreprocstack
else else