Browse Source

compiler: implement Delphi like dynamic array constructors. E.g.: SomeArrayVar := TSomeDynArrayType.Create(value1, value2). (issue #0015385)

git-svn-id: trunk@19045 -
paul 14 years ago
parent
commit
ec29fddda7
6 changed files with 162 additions and 0 deletions
  1. 4 0
      .gitattributes
  2. 98 0
      compiler/pexpr.pas
  3. 20 0
      tests/test/tarrconstr1.pp
  4. 13 0
      tests/test/tarrconstr2.pp
  5. 14 0
      tests/test/tarrconstr3.pp
  6. 13 0
      tests/test/tarrconstr4.pp

+ 4 - 0
.gitattributes

@@ -9765,6 +9765,10 @@ tests/test/tarray6.pp svneol=native#text/plain
 tests/test/tarray7.pp svneol=native#text/plain
 tests/test/tarray8.pp svneol=native#text/plain
 tests/test/tarray9.pp svneol=native#text/plain
+tests/test/tarrconstr1.pp svneol=native#text/pascal
+tests/test/tarrconstr2.pp svneol=native#text/pascal
+tests/test/tarrconstr3.pp svneol=native#text/pascal
+tests/test/tarrconstr4.pp svneol=native#text/pascal
 tests/test/tasm1.pp svneol=native#text/plain
 tests/test/tasm2.pp svneol=native#text/plain
 tests/test/tasm3.pp svneol=native#text/plain

+ 98 - 0
compiler/pexpr.pas

@@ -1868,6 +1868,74 @@ implementation
             p1:=newblock;
           end;
 
+        function parse_array_constructor(arrdef:tarraydef): tnode;
+          var
+            newstatement,assstatement:tstatementnode;
+            arrnode:ttempcreatenode;
+            temp2:ttempcreatenode;
+            assnode,paranode:tnode;
+            paracount:integer;
+          begin
+            result:=internalstatements(newstatement);
+            { create temp for result }
+            arrnode:=ctempcreatenode.create(arrdef,arrdef.size,tt_persistent,true);
+            addstatement(newstatement,arrnode);
+
+            paracount:=0;
+            { check arguments and create an assignment calls }
+            if try_to_consume(_LKLAMMER) then
+              begin
+                assnode:=internalstatements(assstatement);
+                repeat
+                  { arr[i] := param_i }
+                  addstatement(assstatement,
+                    cassignmentnode.create(
+                      cvecnode.create(
+                        ctemprefnode.create(arrnode),
+                        cordconstnode.create(paracount,arrdef.rangedef,false)),
+                      comp_expr(true,false)));
+                  inc(paracount);
+                until not try_to_consume(_COMMA);
+                consume(_RKLAMMER);
+              end
+            else
+              assnode:=nil;
+
+            { get temp for array of lengths }
+            temp2:=ctempcreatenode.create(sinttype,sinttype.size,tt_persistent,false);
+            addstatement(newstatement,temp2);
+
+            { one dimensional }
+            addstatement(newstatement,cassignmentnode.create(
+                ctemprefnode.create_offset(temp2,0),
+                cordconstnode.create
+                   (paracount,s32inttype,true)));
+            { create call to fpc_dynarr_setlength }
+            addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',
+                ccallparanode.create(caddrnode.create_internal
+                      (ctemprefnode.create(temp2)),
+                   ccallparanode.create(cordconstnode.create
+                      (1,s32inttype,true),
+                   ccallparanode.create(caddrnode.create_internal
+                      (crttinode.create(tstoreddef(arrdef),initrtti,rdt_normal)),
+                   ccallparanode.create(
+                     ctypeconvnode.create_internal(
+                       ctemprefnode.create(arrnode),voidpointertype),
+                     nil))))
+
+              ));
+            { add assignment statememnts }
+            addstatement(newstatement,ctempdeletenode.create(temp2));
+            if assigned(assnode) then
+              addstatement(newstatement,assnode);
+            { the last statement should return the value as
+              location and type, this is done be referencing the
+              temp and converting it first from a persistent temp to
+              normal temp }
+            addstatement(newstatement,ctempdeletenode.create_normal_temp(arrnode));
+            addstatement(newstatement,ctemprefnode.create(arrnode));
+          end;
+
         var
           protsym  : tpropertysym;
           p2,p3  : tnode;
@@ -2098,6 +2166,36 @@ implementation
                             end;
                           consume(_ID);
                         end;
+                      arraydef:
+                        begin
+                          if is_dynamic_array(p1.resultdef) then
+                            begin
+                              if token=_ID then
+                                begin
+                                  if pattern='CREATE' then
+                                    begin
+                                      consume(_ID);
+                                      p2:=parse_array_constructor(tarraydef(p1.resultdef));
+                                      p1.destroy;
+                                      p1:=p2;
+                                    end
+                                  else
+                                    begin
+                                      Message2(scan_f_syn_expected,'CREATE',pattern);
+                                      p1.destroy;
+                                      p1:=cerrornode.create;
+                                      consume(_ID);
+                                    end;
+                                end;
+                            end
+                          else
+                            begin
+                              Message(parser_e_invalid_qualifier);
+                              p1.destroy;
+                              p1:=cerrornode.create;
+                              consume(_ID);
+                            end;
+                        end;
                        variantdef:
                          begin
                            { dispatch call? }

+ 20 - 0
tests/test/tarrconstr1.pp

@@ -0,0 +1,20 @@
+program tarrconstr1;
+
+{$mode delphi}
+
+type
+  TAB = array of byte;
+var
+  D: TAB;
+  i: integer;
+begin
+  i:=1;
+  D := TAB.create(1+2, i);
+  if Length(D) <> 2 then
+    halt(1);
+  if D[0] <> 3 then
+    halt(2);
+  if D[1] <> i then
+    halt(3);
+end.
+

+ 13 - 0
tests/test/tarrconstr2.pp

@@ -0,0 +1,13 @@
+{ %fail}
+program tarrconstr2;
+
+{$mode delphi}
+
+type
+  TAB = array of byte;
+var
+  D: TAB;
+begin
+  D := TAB.create(1+2, 'c');
+end.
+

+ 14 - 0
tests/test/tarrconstr3.pp

@@ -0,0 +1,14 @@
+{ %fail}
+program tarrconstr3;
+
+{$mode delphi}
+
+type
+  TAB = array of byte;
+var
+  D: TAB;
+begin
+  // CREATE expected but INIT found
+  D := TAB.init(1, 1);
+end.
+

+ 13 - 0
tests/test/tarrconstr4.pp

@@ -0,0 +1,13 @@
+program tarrconstr4;
+
+{$mode delphi}
+
+type
+  TAB = array[0..1] of byte;
+var
+  D: TAB;
+begin
+  // only dynamic arrays are allowed
+  D := TAB.Create(1, 1);
+end.
+