| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 | {    Copyright (c) 1998-2002 by Florian Klaempfl    This unit handles the pass_typecheck and node conversion pass    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************}unit pass_1;{$i fpcdefs.inc}interface    uses       node;    procedure typecheckpass(var p : tnode);    function  do_typecheckpass(var p : tnode) : boolean;    function  do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;    procedure firstpass(var p : tnode);    function  do_firstpass(var p : tnode) : boolean;{$ifdef state_tracking}    procedure  do_track_state_pass(p:Tnode);{$endif}implementation    uses      globtype,comphook,systems,cclasses,      cutils,globals,      procinfo,      cgbase,symdef{$ifdef extdebug}      ,verbose,htypechk{$endif extdebug}{$ifdef state_tracking}      ,nstate{$endif}      ;{*****************************************************************************                            Global procedures*****************************************************************************}    procedure typecheckpass_internal(var p : tnode; out node_changed: boolean);      var         oldcodegenerror  : boolean;         oldlocalswitches : tlocalswitches;         oldverbosity     : longint;         oldpos    : tfileposinfo;         hp        : tnode;      begin        node_changed:=false;        if (p.resultdef=nil) then         begin           oldcodegenerror:=codegenerror;           oldpos:=current_filepos;           oldlocalswitches:=current_settings.localswitches;           oldverbosity:=status.verbosity;           codegenerror:=false;           current_filepos:=p.fileinfo;           current_settings.localswitches:=p.localswitches;           status.verbosity:=p.verbosity;           hp:=p.pass_typecheck;           { should the node be replaced? }           if assigned(hp) then            begin               node_changed:=true;               p.free;               { switch to new node }               p:=hp;               { run typecheckpass }               typecheckpass(p);            end;           current_settings.localswitches:=oldlocalswitches;           current_filepos:=oldpos;           status.verbosity:=oldverbosity;           if codegenerror then            begin              include(p.flags,nf_error);              { default to errortype if no type is set yet }              if p.resultdef=nil then               p.resultdef:=generrordef;            end;           codegenerror:=codegenerror or oldcodegenerror;         end        else         begin           { update the codegenerror boolean with the previous result of this node }           if (nf_error in p.flags) then             codegenerror:=true;         end;      end;    procedure typecheckpass(var p : tnode);      var        node_changed: boolean;      begin        typecheckpass_internal(p,node_changed);      end;    function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;      begin         codegenerror:=false;         typecheckpass_internal(p,nodechanged);         do_typecheckpass_changed:=codegenerror;      end;    function do_typecheckpass(var p : tnode) : boolean;      var        nodechanged: boolean;      begin         result:=do_typecheckpass_changed(p,nodechanged);      end;    procedure firstpass(var p : tnode);      var         oldcodegenerror  : boolean;         oldlocalswitches : tlocalswitches;         oldpos    : tfileposinfo;         oldverbosity: longint;         hp : tnode;      begin         if (nf_pass1_done in p.flags) then           exit;         if not(nf_error in p.flags) then           begin              oldcodegenerror:=codegenerror;              oldpos:=current_filepos;              oldlocalswitches:=current_settings.localswitches;              oldverbosity:=status.verbosity;              codegenerror:=false;              current_filepos:=p.fileinfo;              current_settings.localswitches:=p.localswitches;              status.verbosity:=p.verbosity;              { checks make always a call }              if ([cs_check_range,cs_check_overflow,cs_check_stack] * current_settings.localswitches <> []) then                include(current_procinfo.flags,pi_do_call);              { determine the resultdef if not done }              if (p.resultdef=nil) then                begin                  hp:=p.pass_typecheck;                  { should the node be replaced? }                  if assigned(hp) then                   begin                      p.free;                      { switch to new node }                      p:=hp;                      { run typecheckpass }                      typecheckpass(p);                   end;                  if codegenerror then                   begin                     include(p.flags,nf_error);                     { default to errortype if no type is set yet }                     if p.resultdef=nil then                      p.resultdef:=generrordef;                   end;                  codegenerror:=codegenerror or oldcodegenerror;                end;              if not(nf_error in p.flags) then                begin                  { first pass }                  hp:=p.pass_1;                  { should the node be replaced? }                  if assigned(hp) then                   begin                     p.free;                     { switch to new node }                     p := hp;                     { run firstpass }                     firstpass(p);                   end                  else                    begin                      { inlining happens in pass_1 and can cause new }                      { simplify opportunities                       }                      hp:=p.simplify(true);                      if assigned(hp) then                        begin                          p.free;                          p := hp;                          firstpass(p);                        end;                    end;                  if codegenerror then                   include(p.flags,nf_error)                  else                   begin{$ifdef EXTDEBUG}                     if (p.expectloc=LOC_INVALID) then                       Comment(V_Warning,'Expectloc is not set in firstpass: '+nodetype2str[p.nodetype]);{$endif EXTDEBUG}                   end;                end;              include(p.flags,nf_pass1_done);              codegenerror:=codegenerror or oldcodegenerror;              current_settings.localswitches:=oldlocalswitches;              current_filepos:=oldpos;              status.verbosity:=oldverbosity;           end         else           codegenerror:=true;      end;    function do_firstpass(var p : tnode) : boolean;      begin         codegenerror:=false;         firstpass(p);{$ifdef state_tracking}         writeln('TRACKSTART');         writeln('before');         writenode(p);         do_track_state_pass(p);         writeln('after');         writenode(p);         writeln('TRACKDONE');{$endif}         do_firstpass:=codegenerror;      end;{$ifdef state_tracking}     procedure do_track_state_pass(p:Tnode);     begin        aktstate:=Tstate_storage.create;        p.track_state_pass(true);            aktstate.destroy;     end;{$endif}end.
 |