[fpc-devel] Parsing procedural type and method directives

Blaise at blaise.ru Blaise at blaise.ru
Tue Dec 21 21:37:14 CET 2021


1) The following three routines:
	pdecsub.pas!parse_parameter_dec
	pdecvar.pas!maybe_parse_proc_directives
	ptype.pas!read_named_type\procvar_dec
create a dummy typesym for the procdef, for the sole purpose of invoking parse_var_proc_directives, which merely extracts that procdef. The attached parse_proctype_directives-1.patch replaces these hacks with calls to the new routine parse_proctype_directives that takes a procvardef directly.


2) Now, there remain three callers of the old parse_var_proc_directives:
	pdecl.pas!consts_dec x2
	pdecl.pas!types_dec
	pgenutil.pas!generate_specialization_phase2
and all of them have procvardefs readily available. The attached parse_proctype_directives-2.patch drops parse_var_proc_directives in favour of parse_proctype_directives.

P.S. It seems that the cases localvarsym and paravarsym @ parse_var_proc_directives were unreachable.


3) The attached consts_dec.patch refactors consts_dec:
	skipequal -> skip_initialiser, with better locality;
	deduplicates:
		calls to check_proc_directive & parse_proctype_directives;
		checks of current_settings;
		indexations of current_asmdata.asmlists;
	elucidates comments.


4) The attached pdflags.patch removes the line
> pdflags:=pdflags+[pd_body,pd_implemen];
from pgenutil.pas!generate_specialization_phase2. The variable pdflags is not used after that statement; thus, it is confusing: makes the code look like some related logic is missing.


5) The attached parse_objrec_proc_directives.patch changes parse_object_proc_directives & parse_record_proc_directives to take tprocdef instead of tabstractprocdef.

-- 
βþ
-------------- next part --------------
# HG changeset patch
# User Blaise.ru
# Date 1640117985 -10800
#      Tue Dec 21 23:19:45 2021 +0300
= parse_parameter_dec, maybe_parse_proc_directives, read_named_type\procvar_dec: instead of calling parse_var_proc_directives(dummy-typesym), call new parse_proctype_directives(tprocvardef)

diff -r d880e6695537 -r a2bda2c4af8e pdecsub.pas
--- a/pdecsub.pas	Mon Dec 20 20:55:22 2021 +0300
+++ b/pdecsub.pas	Tue Dec 21 23:19:45 2021 +0300
@@ -63,6 +63,7 @@
     procedure parse_parameter_dec(pd:tabstractprocdef);
     procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
     procedure parse_var_proc_directives(sym:tsym);
+    procedure parse_proctype_directives(pd:tprocvardef);
     procedure parse_object_proc_directives(pd:tabstractprocdef);
     procedure parse_record_proc_directives(pd:tabstractprocdef);
     function  parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;isgeneric:boolean;genericdef:tdef;generictypelist:tfphashobjectlist;out pd:tprocdef):boolean;
@@ -212,7 +213,6 @@
         parseprocvar : tppv;
         locationstr : string;
         paranr : integer;
-        dummytype : ttypesym;
         explicit_paraloc,
         need_array,
         is_univ: boolean;
@@ -346,22 +346,16 @@
                 single_type(pv.returndef,[]);
                 block_type:=bt_var;
               end;
-             hdef:=pv;
              { possible proc directives }
              if check_proc_directive(true) then
-               begin
-                  dummytype:=ctypesym.create('unnamed',hdef);
-                  parse_var_proc_directives(tsym(dummytype));
-                  dummytype.typedef:=nil;
-                  hdef.typesym:=nil;
-                  dummytype.free;
-               end;
+               parse_proctype_directives(pv);
              { Add implicit hidden parameters and function result }
              handle_calling_convention(pv,hcc_default_actions_intf);
 {$ifdef jvm}
              { anonymous -> no name }
              jvm_create_procvar_class('',pv);
 {$endif}
+             hdef:=pv;
            end
           else
           { read type declaration, force reading for value paras }
@@ -3406,25 +3400,29 @@
 
     procedure parse_var_proc_directives(sym:tsym);
       var
-        pdflags : tpdflags;
-        pd      : tabstractprocdef;
+        pd      : tprocvardef;
       begin
-        pdflags:=[pd_procvar];
-        pd:=nil;
         case sym.typ of
           fieldvarsym,
           staticvarsym,
           localvarsym,
           paravarsym :
-            pd:=tabstractprocdef(tabstractvarsym(sym).vardef);
+            pd:=tprocvardef(tabstractvarsym(sym).vardef);
           typesym :
-            pd:=tabstractprocdef(ttypesym(sym).typedef);
+            pd:=tprocvardef(ttypesym(sym).typedef);
           else
             internalerror(2003042617);
         end;
         if pd.typ<>procvardef then
           internalerror(2003042618);
-        { names should never be used anyway }
+        parse_proctype_directives(pd);
+      end;
+
+    procedure parse_proctype_directives(pd:tprocvardef);
+      var
+        pdflags : tpdflags;
+      begin
+        pdflags:=[pd_procvar];
         parse_proc_directives(pd,pdflags);
       end;
 
diff -r d880e6695537 -r a2bda2c4af8e pdecvar.pas
--- a/pdecvar.pas	Mon Dec 20 20:55:22 2021 +0300
+++ b/pdecvar.pas	Tue Dec 21 23:19:45 2021 +0300
@@ -886,8 +886,6 @@
 
 
      function maybe_parse_proc_directives(def:tdef):boolean;
-       var
-         newtype : ttypesym;
        begin
          result:=false;
          { Process procvar directives before = and ; }
@@ -895,11 +893,7 @@
             (def.typesym=nil) and
             check_proc_directive(true) then
            begin
-              newtype:=ctypesym.create('unnamed',def);
-              parse_var_proc_directives(tsym(newtype));
-              newtype.typedef:=nil;
-              def.typesym:=nil;
-              newtype.free;
+              parse_proctype_directives(tprocvardef(def));
               result:=true;
            end;
        end;
diff -r d880e6695537 -r a2bda2c4af8e ptype.pas
--- a/ptype.pas	Mon Dec 20 20:55:22 2021 +0300
+++ b/ptype.pas	Tue Dec 21 23:19:45 2021 +0300
@@ -1562,8 +1562,7 @@
         function procvar_dec(genericdef:tstoreddef;genericlist:tfphashobjectlist):tdef;
           var
             is_func:boolean;
-            pd:tabstractprocdef;
-            newtype:ttypesym;
+            pd:tprocvardef;
             old_current_genericdef,
             old_current_specializedef: tstoreddef;
             old_parse_generic: boolean;
@@ -1622,18 +1621,11 @@
               end;
             symtablestack.pop(pd.parast);
             tparasymtable(pd.parast).readonly:=false;
-            result:=pd;
             { possible proc directives }
             if parseprocvardir then
               begin
                 if check_proc_directive(true) then
-                  begin
-                    newtype:=ctypesym.create('unnamed',result);
-                    parse_var_proc_directives(tsym(newtype));
-                    newtype.typedef:=nil;
-                    result.typesym:=nil;
-                    newtype.free;
-                  end;
+                  parse_proctype_directives(pd);
                 { Add implicit hidden parameters and function result }
                 handle_calling_convention(pd,hcc_default_actions_intf);
               end;
@@ -1641,6 +1633,8 @@
             parse_generic:=old_parse_generic;
             current_genericdef:=old_current_genericdef;
             current_specializedef:=old_current_specializedef;
+
+            result:=pd;
           end;
 
       const
-------------- next part --------------
# HG changeset patch
# User Blaise.ru
# Date 1640053801 -10800
#      Tue Dec 21 05:30:01 2021 +0300
= consts_dec, types_dec, generate_specialization_phase2: parse_var_proc_directives(tsym) -> parse_proctype_directives(tprocvardef)

diff -r a2bda2c4af8e -r b05f9e671444 pdecl.pas
--- a/pdecl.pas	Tue Dec 21 23:19:45 2021 +0300
+++ b/pdecl.pas	Tue Dec 21 05:30:01 2021 +0300
@@ -323,7 +323,7 @@
                       if try_to_consume(_SEMICOLON) then
                        begin
                          if check_proc_directive(true) then
-                          parse_var_proc_directives(sym)
+                          parse_proctype_directives(tprocvardef(hdef))
                          else
                           begin
                             Message(parser_e_proc_directive_expected);
@@ -334,7 +334,7 @@
                       { support p : procedure stdcall=nil; }
                        begin
                          if check_proc_directive(true) then
-                          parse_var_proc_directives(sym);
+                          parse_proctype_directives(tprocvardef(hdef));
                        end;
                       { add default calling convention }
                       handle_calling_convention(tabstractprocdef(hdef),hcc_default_actions_intf);
@@ -1079,7 +1079,7 @@
                            try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
                            consume(_SEMICOLON);
                          end;
-                       parse_var_proc_directives(tsym(newtype));
+                       parse_proctype_directives(tprocvardef(hdef));
                        if po_is_function_ref in tprocvardef(hdef).procoptions then
                          begin
                            { these always support everything, no "of object" or
diff -r a2bda2c4af8e -r b05f9e671444 pdecsub.pas
--- a/pdecsub.pas	Tue Dec 21 23:19:45 2021 +0300
+++ b/pdecsub.pas	Tue Dec 21 05:30:01 2021 +0300
@@ -62,7 +62,6 @@
 
     procedure parse_parameter_dec(pd:tabstractprocdef);
     procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
-    procedure parse_var_proc_directives(sym:tsym);
     procedure parse_proctype_directives(pd:tprocvardef);
     procedure parse_object_proc_directives(pd:tabstractprocdef);
     procedure parse_record_proc_directives(pd:tabstractprocdef);
@@ -3398,26 +3397,6 @@
       end;
 
 
-    procedure parse_var_proc_directives(sym:tsym);
-      var
-        pd      : tprocvardef;
-      begin
-        case sym.typ of
-          fieldvarsym,
-          staticvarsym,
-          localvarsym,
-          paravarsym :
-            pd:=tprocvardef(tabstractvarsym(sym).vardef);
-          typesym :
-            pd:=tprocvardef(ttypesym(sym).typedef);
-          else
-            internalerror(2003042617);
-        end;
-        if pd.typ<>procvardef then
-          internalerror(2003042618);
-        parse_proctype_directives(pd);
-      end;
-
     procedure parse_proctype_directives(pd:tprocvardef);
       var
         pdflags : tpdflags;
@@ -3426,7 +3405,6 @@
         parse_proc_directives(pd,pdflags);
       end;
 
-
     procedure parse_object_proc_directives(pd:tabstractprocdef);
       var
         pdflags : tpdflags;
diff -r a2bda2c4af8e -r b05f9e671444 pgenutil.pas
--- a/pgenutil.pas	Tue Dec 21 23:19:45 2021 +0300
+++ b/pgenutil.pas	Tue Dec 21 05:30:01 2021 +0300
@@ -1248,7 +1248,7 @@
                             hintsprocessed:=true;
                         end;
                       if replaydepth>current_scanner.replay_stack_depth then
-                        parse_var_proc_directives(ttypesym(srsym));
+                        parse_proctype_directives(tprocvardef(result));
                       handle_calling_convention(tprocvardef(result),hcc_default_actions_intf);
                       if not hintsprocessed and (replaydepth>current_scanner.replay_stack_depth) then
                         begin
-------------- next part --------------
# HG changeset patch
# User Blaise.ru
# Date 1640114015 -10800
#      Tue Dec 21 22:13:35 2021 +0300
= consts_dec: deduplicate calls to check_proc_directive & parse_proctype_directives, checks of current_settings, and indexations of current_asmdata.asmlists

diff -r b05f9e671444 -r 71856f37bb17 pdecl.pas
--- a/pdecl.pas	Tue Dec 21 05:30:01 2021 +0300
+++ b/pdecl.pas	Tue Dec 21 22:13:35 2021 +0300
@@ -227,9 +227,10 @@
          old_block_type : tblock_type;
          first,
          isgeneric,
-         skipequal : boolean;
-         tclist : tasmlist;
+         expect_directive,
+         skip_initialiser : boolean;
          varspez : tvarspez;
+         asmtype : TAsmListType;
       begin
          old_block_type:=block_type;
          block_type:=bt_const;
@@ -287,14 +288,19 @@
                    consume(_COLON);
                    read_anon_type(hdef,false);
                    block_type:=bt_const;
-                   skipequal:=false;
                    { create symbol }
                    storetokenpos:=current_tokenpos;
                    current_tokenpos:=filepos;
                    if not (cs_typed_const_writable in current_settings.localswitches) then
-                     varspez:=vs_const
+                     begin
+                       varspez:=vs_const;
+                       asmtype:=al_rotypedconsts;
+                     end
                    else
-                     varspez:=vs_value;
+                     begin
+                       varspez:=vs_value;
+                       asmtype:=al_typedconsts;
+                     end;
                    { if we are dealing with structure const then we need to handle it as a
                      structure static variable: create a symbol in unit symtable and a reference
                      to it from the structure or linking will fail }
@@ -315,39 +321,28 @@
                      end;
                    sym.register_sym;
                    current_tokenpos:=storetokenpos;
-                   { procvar can have proc directives, but not type references }
+                   skip_initialiser:=false;
+                   { Anonymous proctype definitions can have proc directives }
                    if (hdef.typ=procvardef) and
                       (hdef.typesym=nil) then
                     begin
-                      { support p : procedure;stdcall=nil; }
-                      if try_to_consume(_SEMICOLON) then
+                      { Either "procedure; stdcall" or "procedure stdcall" }
+                      expect_directive:=try_to_consume(_SEMICOLON);
+                      if check_proc_directive(true) then
+                        parse_proctype_directives(tprocvardef(hdef))
+                      else if expect_directive then
                        begin
-                         if check_proc_directive(true) then
-                          parse_proctype_directives(tprocvardef(hdef))
-                         else
-                          begin
-                            Message(parser_e_proc_directive_expected);
-                            skipequal:=true;
-                          end;
-                       end
-                      else
-                      { support p : procedure stdcall=nil; }
-                       begin
-                         if check_proc_directive(true) then
-                          parse_proctype_directives(tprocvardef(hdef));
+                         Message(parser_e_proc_directive_expected);
+                         skip_initialiser:=true;
                        end;
                       { add default calling convention }
                       handle_calling_convention(tabstractprocdef(hdef),hcc_default_actions_intf);
                     end;
-                   if not skipequal then
+                   { Parse the initialiser }
+                   if not skip_initialiser then
                     begin
-                      { get init value }
                       consume(_EQ);
-                      if (cs_typed_const_writable in current_settings.localswitches) then
-                        tclist:=current_asmdata.asmlists[al_typedconsts]
-                      else
-                        tclist:=current_asmdata.asmlists[al_rotypedconsts];
-                      read_typed_const(tclist,tstaticvarsym(sym),in_structure);
+                      read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(sym),in_structure);
                     end;
                 end;
 
-------------- next part --------------
# HG changeset patch
# User Blaise.ru
# Date 1640115809 -10800
#      Tue Dec 21 22:43:29 2021 +0300
= generate_specialization_phase2: remove bogus pdflags manipulation

diff -r 71856f37bb17 -r be7ac48a05fb pgenutil.pas
--- a/pgenutil.pas	Tue Dec 21 22:13:35 2021 +0300
+++ b/pgenutil.pas	Tue Dec 21 22:43:29 2021 +0300
@@ -1271,7 +1271,6 @@
                         handle_calling_convention(tprocdef(result),hcc_default_actions_intf)
                       else
                         handle_calling_convention(tprocdef(result),hcc_default_actions_impl);
-                      pdflags:=pdflags+[pd_body,pd_implemen];
                       proc_add_definition(tprocdef(result));
                       { for partial specializations we implicitely declare the routine as
                         having its implementation although we'll not specialize it in reality }
-------------- next part --------------
# HG changeset patch
# User Blaise.ru
# Date 1640116911 -10800
#      Tue Dec 21 23:01:51 2021 +0300
= parse_object_proc_directives & parse_record_proc_directives: take tprocdef instead of tabstractprocdef

diff -r be7ac48a05fb -r 768020dbe0c6 pdecsub.pas
--- a/pdecsub.pas	Tue Dec 21 22:43:29 2021 +0300
+++ b/pdecsub.pas	Tue Dec 21 23:01:51 2021 +0300
@@ -63,8 +63,8 @@
     procedure parse_parameter_dec(pd:tabstractprocdef);
     procedure parse_proc_directives(pd:tabstractprocdef;var pdflags:tpdflags);
     procedure parse_proctype_directives(pd:tprocvardef);
-    procedure parse_object_proc_directives(pd:tabstractprocdef);
-    procedure parse_record_proc_directives(pd:tabstractprocdef);
+    procedure parse_object_proc_directives(pd:tprocdef);
+    procedure parse_record_proc_directives(pd:tprocdef);
     function  parse_proc_head(astruct:tabstractrecorddef;potype:tproctypeoption;isgeneric:boolean;genericdef:tdef;generictypelist:tfphashobjectlist;out pd:tprocdef):boolean;
     function  parse_proc_dec(isclassmethod:boolean;astruct:tabstractrecorddef;isgeneric:boolean):tprocdef;
     procedure parse_proc_dec_finish(pd:tprocdef;isclassmethod:boolean;astruct:tabstractrecorddef);
@@ -3405,7 +3405,7 @@
         parse_proc_directives(pd,pdflags);
       end;
 
-    procedure parse_object_proc_directives(pd:tabstractprocdef);
+    procedure parse_object_proc_directives(pd:tprocdef);
       var
         pdflags : tpdflags;
       begin
@@ -3413,7 +3413,7 @@
         parse_proc_directives(pd,pdflags);
       end;
 
-    procedure parse_record_proc_directives(pd:tabstractprocdef);
+    procedure parse_record_proc_directives(pd:tprocdef);
       var
         pdflags : tpdflags;
       begin


More information about the fpc-devel mailing list