浏览代码

compiler: implement properties in records:
- rename property_dec from pdecobj to struct_property_dec because pdecl also has property_dec and move it to interface to use by records + allow properties for records
- use struct_property_dec in record parser
- change structh type from objectdef to abstractrecorddef in read_property_dec to use by records
- disallow stored and default modifiers for records because records are not used for streaming
- fix misuse of search_sym_in_class for records in few places

git-svn-id: branches/paul/extended_records@16548 -

paul 14 年之前
父节点
当前提交
17815ce7a2
共有 7 个文件被更改,包括 58 次插入24 次删除
  1. 1 1
      compiler/dbgdwarf.pas
  2. 11 10
      compiler/pdecobj.pas
  3. 14 10
      compiler/pdecvar.pas
  4. 8 2
      compiler/pexpr.pas
  5. 1 1
      compiler/ptype.pas
  6. 6 0
      tests/test/terecs3.pp
  7. 17 0
      tests/test/terecs_u1.pp

+ 1 - 1
compiler/dbgdwarf.pas

@@ -2675,7 +2675,7 @@ implementation
         if not get_symlist_sym_offset(symlist,tosym,offset) then
         if not get_symlist_sym_offset(symlist,tosym,offset) then
           exit;
           exit;
 
 
-        if (tosym.owner.symtabletype<>objectsymtable) then
+        if not (tosym.owner.symtabletype in [objectsymtable,recordsymtable]) then
           begin
           begin
             if (tosym.typ=fieldvarsym) then
             if (tosym.typ=fieldvarsym) then
               internalerror(2009031404);
               internalerror(2009031404);

+ 11 - 10
compiler/pdecobj.pas

@@ -36,6 +36,7 @@ interface
     function class_destructor_head:tprocdef;
     function class_destructor_head:tprocdef;
     function constructor_head:tprocdef;
     function constructor_head:tprocdef;
     function destructor_head:tprocdef;
     function destructor_head:tprocdef;
+    procedure struct_property_dec(is_classproperty:boolean);
 
 
 implementation
 implementation
 
 
@@ -111,22 +112,22 @@ implementation
       end;
       end;
 
 
 
 
-    procedure property_dec(is_classproperty:boolean);
+    procedure struct_property_dec(is_classproperty:boolean);
       var
       var
         p : tpropertysym;
         p : tpropertysym;
       begin
       begin
-        { check for a class }
-        if not((is_class_or_interface_or_dispinterface(current_objectdef)) or
-           (not(m_tp7 in current_settings.modeswitches) and (is_object(current_objectdef)))) then
+        { check for a class or record }
+        if not((is_class_or_interface_or_dispinterface(current_structdef) or is_record(current_structdef)) or
+           (not(m_tp7 in current_settings.modeswitches) and (is_object(current_structdef)))) then
           Message(parser_e_syntax_error);
           Message(parser_e_syntax_error);
         consume(_PROPERTY);
         consume(_PROPERTY);
-        p:=read_property_dec(is_classproperty, current_objectdef);
+        p:=read_property_dec(is_classproperty,current_structdef);
         consume(_SEMICOLON);
         consume(_SEMICOLON);
         if try_to_consume(_DEFAULT) then
         if try_to_consume(_DEFAULT) then
           begin
           begin
-            if oo_has_default_property in current_objectdef.objectoptions then
+            if oo_has_default_property in current_structdef.objectoptions then
               message(parser_e_only_one_default_property);
               message(parser_e_only_one_default_property);
-            include(current_objectdef.objectoptions,oo_has_default_property);
+            include(current_structdef.objectoptions,oo_has_default_property);
             include(p.propoptions,ppo_defaultproperty);
             include(p.propoptions,ppo_defaultproperty);
             if not(ppo_hasparameters in p.propoptions) then
             if not(ppo_hasparameters in p.propoptions) then
               message(parser_e_property_need_paras);
               message(parser_e_property_need_paras);
@@ -144,11 +145,11 @@ implementation
             begin
             begin
               if pattern='CURRENT' then
               if pattern='CURRENT' then
               begin
               begin
-                if oo_has_enumerator_current in current_objectdef.objectoptions then
+                if oo_has_enumerator_current in current_structdef.objectoptions then
                   message(parser_e_only_one_enumerator_current);
                   message(parser_e_only_one_enumerator_current);
                 if not p.propaccesslist[palt_read].empty then
                 if not p.propaccesslist[palt_read].empty then
                 begin
                 begin
-                  include(current_objectdef.objectoptions,oo_has_enumerator_current);
+                  include(current_structdef.objectoptions,oo_has_enumerator_current);
                   include(p.propoptions,ppo_enumerator_current);
                   include(p.propoptions,ppo_enumerator_current);
                 end
                 end
                 else
                 else
@@ -764,7 +765,7 @@ implementation
               end;
               end;
             _PROPERTY :
             _PROPERTY :
               begin
               begin
-                property_dec(is_classdef);
+                struct_property_dec(is_classdef);
                 fields_allowed:=false;
                 fields_allowed:=false;
                 is_classdef:=false;
                 is_classdef:=false;
               end;
               end;

+ 14 - 10
compiler/pdecvar.pas

@@ -33,7 +33,7 @@ interface
       tvar_dec_option=(vd_record,vd_object,vd_threadvar,vd_class);
       tvar_dec_option=(vd_record,vd_object,vd_threadvar,vd_class);
       tvar_dec_options=set of tvar_dec_option;
       tvar_dec_options=set of tvar_dec_option;
 
 
-    function  read_property_dec(is_classproperty:boolean;astruct:tobjectdef):tpropertysym;
+    function  read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
 
 
     procedure read_var_decls(options:Tvar_dec_options);
     procedure read_var_decls(options:Tvar_dec_options);
 
 
@@ -66,7 +66,7 @@ implementation
        ;
        ;
 
 
 
 
-    function read_property_dec(is_classproperty:boolean;astruct:tobjectdef):tpropertysym;
+    function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
 
 
         { convert a node tree to symlist and return the last
         { convert a node tree to symlist and return the last
           symbol }
           symbol }
@@ -279,7 +279,7 @@ implementation
                   pt.free;
                   pt.free;
                 end
                 end
               else
               else
-                p.dispid:=astruct.get_next_dispid;
+                p.dispid:=tobjectdef(astruct).get_next_dispid;
             end;
             end;
 
 
           procedure add_index_parameter(var paranr: word; p: tpropertysym; readprocdef, writeprocdef, storedprocdef: tprocvardef);
           procedure add_index_parameter(var paranr: word; p: tpropertysym; readprocdef, writeprocdef, storedprocdef: tprocvardef);
@@ -457,7 +457,10 @@ implementation
          else
          else
            begin
            begin
               { do an property override }
               { do an property override }
-              overridden:=search_struct_member(astruct.childof,p.name);
+              if (astruct.typ=objectdef) then
+                overridden:=search_struct_member(tobjectdef(astruct).childof,p.name)
+              else
+                overridden:=nil;
               if assigned(overridden) and
               if assigned(overridden) and
                  (overridden.typ=propertysym) and
                  (overridden.typ=propertysym) and
                  not(is_dispinterface(astruct)) then
                  not(is_dispinterface(astruct)) then
@@ -585,7 +588,8 @@ implementation
          else
          else
            parse_dispinterface(p);
            parse_dispinterface(p);
 
 
-         if assigned(astruct) and not(is_dispinterface(astruct)) and not is_classproperty then
+         { stored is not allowed for dispinterfaces, records or class properties }
+         if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
            begin
            begin
              { ppo_stored is default on for not overridden properties }
              { ppo_stored is default on for not overridden properties }
              if not assigned(p.overriddenpropsym) then
              if not assigned(p.overriddenpropsym) then
@@ -672,7 +676,7 @@ implementation
                 end;
                 end;
               end;
               end;
            end;
            end;
-         if try_to_consume(_DEFAULT) then
+         if not is_record(astruct) and try_to_consume(_DEFAULT) then
            begin
            begin
               if not allow_default_property(p) then
               if not allow_default_property(p) then
                 begin
                 begin
@@ -713,7 +717,7 @@ implementation
                   pt.free;
                   pt.free;
                 end;
                 end;
            end
            end
-         else if try_to_consume(_NODEFAULT) then
+         else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
            begin
            begin
               p.default:=longint($80000000);
               p.default:=longint($80000000);
            end;
            end;
@@ -724,7 +728,7 @@ implementation
            end;
            end;
 *)
 *)
          { Parse possible "implements" keyword }
          { Parse possible "implements" keyword }
-         if try_to_consume(_IMPLEMENTS) then
+         if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
            begin
            begin
              single_type(def,false,false);
              single_type(def,false,false);
 
 
@@ -782,9 +786,9 @@ implementation
                  exit;
                  exit;
                end;
                end;
              found:=false;
              found:=false;
-             for i:=0 to astruct.ImplementedInterfaces.Count-1 do
+             for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
                begin
                begin
-                 ImplIntf:=TImplementedInterface(astruct.ImplementedInterfaces[i]);
+                 ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
 
 
                  if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
                  if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
                    begin
                    begin

+ 8 - 2
compiler/pexpr.pas

@@ -1083,7 +1083,10 @@ implementation
                          if (sp_static in sym.symoptions) then
                          if (sp_static in sym.symoptions) then
                            begin
                            begin
                              static_name:=lower(sym.owner.name^)+'_'+sym.name;
                              static_name:=lower(sym.owner.name^)+'_'+sym.name;
-                             searchsym_in_class(tobjectdef(sym.owner.defowner),tobjectdef(sym.owner.defowner),static_name,sym,srsymtable);
+                             if sym.owner.defowner.typ=objectdef then
+                               searchsym_in_class(tobjectdef(sym.owner.defowner),tobjectdef(sym.owner.defowner),static_name,sym,srsymtable)
+                             else
+                               searchsym_in_record(trecorddef(sym.owner.defowner),static_name,sym,srsymtable);
                              if assigned(sym) then
                              if assigned(sym) then
                                check_hints(sym,sym.symoptions,sym.deprecatedmsg);
                                check_hints(sym,sym.symoptions,sym.deprecatedmsg);
                              p1.free;
                              p1.free;
@@ -1134,7 +1137,10 @@ implementation
                          if (sp_static in sym.symoptions) then
                          if (sp_static in sym.symoptions) then
                            begin
                            begin
                              static_name:=lower(sym.owner.name^)+'_'+sym.name;
                              static_name:=lower(sym.owner.name^)+'_'+sym.name;
-                             searchsym_in_class(tobjectdef(sym.owner.defowner),tobjectdef(sym.owner.defowner),static_name,sym,srsymtable);
+                             if sym.owner.defowner.typ=objectdef then
+                               searchsym_in_class(tobjectdef(sym.owner.defowner),tobjectdef(sym.owner.defowner),static_name,sym,srsymtable)
+                             else
+                               searchsym_in_record(trecorddef(sym.owner.defowner),static_name,sym,srsymtable);
                              if assigned(sym) then
                              if assigned(sym) then
                                check_hints(sym,sym.symoptions,sym.deprecatedmsg);
                                check_hints(sym,sym.symoptions,sym.deprecatedmsg);
                              p1.free;
                              p1.free;

+ 1 - 1
compiler/ptype.pas

@@ -701,7 +701,7 @@ implementation
               end;
               end;
             _PROPERTY :
             _PROPERTY :
               begin
               begin
-                property_dec(is_classdef);
+                struct_property_dec(is_classdef);
                 fields_allowed:=false;
                 fields_allowed:=false;
                 is_classdef:=false;
                 is_classdef:=false;
               end;
               end;

+ 6 - 0
tests/test/terecs3.pp

@@ -23,5 +23,11 @@ begin
     halt(5);
     halt(5);
   if F.F5 <> 6 then
   if F.F5 <> 6 then
     halt(6);
     halt(6);
+  F.P3 := 7;
+  if F.P3 <> 7 then
+    halt(7);
+  F.P5 := 8;
+  if F.P5 <> 8 then
+    halt(8);
   WriteLn('ok');
   WriteLn('ok');
 end.
 end.

+ 17 - 0
tests/test/terecs_u1.pp

@@ -23,6 +23,13 @@ type
       F5: TBar;
       F5: TBar;
     function Test(n: TBar): TBar;
     function Test(n: TBar): TBar;
     class function Test1(n: TBar): TBar;
     class function Test1(n: TBar): TBar;
+
+    procedure Set3(const Value: TBar);
+    class procedure Set5(const Value: TBar); static;
+
+    property P3: TBar read F3 write Set3;
+    class property P5: TBar read F5 write Set5;
+
     class constructor Create;
     class constructor Create;
     class destructor Destroy;
     class destructor Destroy;
   end;
   end;
@@ -49,4 +56,14 @@ begin
   WriteLn('TFoo.Destroy');
   WriteLn('TFoo.Destroy');
 end;
 end;
 
 
+procedure TFoo.Set3(const Value: TBar);
+begin
+  F3 := Value;
+end;
+
+class procedure TFoo.Set5(const Value: TBar); static;
+begin
+  F5 := Value;
+end;
+
 end.
 end.