Browse Source

ISPP: Array variables declared with #dim can now be initialized directly, like #dim MyArray[3] {1, '2', 3} for example.

Martijn Laan 6 years ago
parent
commit
5a938cdd20
4 changed files with 45 additions and 10 deletions
  1. 6 2
      Projects/ISPP/Help/ispp.xml
  2. 3 2
      Projects/ISPP/IsppIdentMan.pas
  3. 31 5
      Projects/ISPP/IsppTranslate.pas
  4. 5 1
      whatsnew.htm

+ 6 - 2
Projects/ISPP/Help/ispp.xml

@@ -165,7 +165,7 @@
         </keywords>
 				<syntax>
 					<define id="dim-directive">
-						<txt>dim</txt><opt><nt name="locality"/></opt><nt>ident</nt><nt name="index-spec"/>
+						<txt>dim</txt><opt><nt name="locality"/></opt><nt>ident</nt><nt name="index-spec"/><opt><nt name="initializers-spec"/></opt>
 					</define>
 					<define id="redim-directive">
 						<txt>redim</txt><opt><nt name="locality"/></opt><nt>ident</nt><nt name="index-spec"/>
@@ -173,9 +173,12 @@
 					<define id="index-spec" inline="yes">
 						<txt>[</txt><nt>expr</nt><txt>]</txt>
 					</define>
+					<define id="initializers-spec" inline="yes">
+						<txt>{</txt><nt>expr</nt><opt repeated="yes"><txt>,</txt><nt>expr</nt></opt><txt>}</txt>
+					</define>
 				</syntax>
 				<description>
-					<para>Use &dim; to declare an array variable and set its dimension. All elements of the array are initialized to null (void). To assign an element value after declaring the array, use &define;. Instead of assigning element values with &define;, it is also possible to set an element value by using it as the left operand of an assignment.</para>
+					<para>Use &dim; to declare an array variable, set its dimension and optionally intialize it. All unitialized elements of the array are initialized to null (void). To assign an element value after declaring the array, use &define;. Instead of assigning element values with &define;, it is also possible to set an element value by using it as the left operand of an assignment.</para>
 					<para>Use &redim; to increase or decrease the dimension of an existing array variable. All new elements of the array are initialized to null (void) and existing elements are left unchanged. Identical to &dim; if <synel>ident</synel> isn't an existing array variable.</para>
 				</description>
 				<section title="Examples">
@@ -185,6 +188,7 @@
 						<line>#redim MyArray[20]</line>
 						<line>#define MyArray[10] 30</line>
 						<line>#redim MyArray[10]</line>
+						<line>#dim MyArray2[3] {1, '2', 3}</line>
 					</pre>
 				</section>
 				<section title="See also">

+ 3 - 2
Projects/ISPP/IsppIdentMan.pas

@@ -95,7 +95,7 @@ type
     procedure DefineVariable(const Name: string; Index: Integer;
       const Value: TIsppVariant; Scope: TDefineScope);
     procedure Delete(const Name: string; Scope: TDefineScope);
-    procedure DimVariable(const Name: string; Length: Integer; Scope: TDefineScope; ReDim: Boolean);
+    procedure DimVariable(const Name: string; Length: Integer; Scope: TDefineScope; var ReDim: Boolean);
     function GetIdent(const Name: string; out CallContext: ICallContext): TIdentType;
     function TypeOf(const Name: string): Byte;
     function DimOf(const Name: String): Integer;
@@ -830,7 +830,7 @@ begin
 end;
 
 procedure TIdentManager.DimVariable(const Name: string; Length: Integer;
-  Scope: TDefineScope; ReDim: Boolean);
+  Scope: TDefineScope; var ReDim: Boolean);
 var
   V, VOld: PVariable;
   I, ReDimIndex: Integer;
@@ -845,6 +845,7 @@ begin
          ((PIdent(FVarMan[ReDimIndex]).IdentType <> itVariable) or
           (PVariable(FVarMan[ReDimIndex]).Dim = 0)) then
         ReDimIndex := -1; //not a variable or not an array, #dim normally
+      ReDim := ReDimIndex <> -1;
     end else
       ReDimIndex := -1;
 

+ 31 - 5
Projects/ISPP/IsppTranslate.pas

@@ -607,18 +607,41 @@ function TPreprocessor.ProcessPreprocCommand(Command: TPreprocessorCommand;
 
   procedure ParseDim(Parser: TParserAccess; ReDim: Boolean);
   var
-    V: string;
-    N: Integer;
+    Name: string;
+    N, NValues, I: Integer;
     Scope: TDefineScope;
+    Values: array of TIsppVariant;
   begin
     with Parser do
     try
       Scope := GetScope(Parser);
-      V := CheckReservedIdent(TokenString);
+      Name := CheckReservedIdent(TokenString);
       NextTokenExpect([tkOpenBracket]);
       N := IntExpr(True);
+      NValues := 0;
       NextTokenExpect([tkCloseBracket]);
-      FIdentManager.DimVariable(V, N, Scope, ReDim);
+      if PeekAtNextToken = tkOpenBrace then
+        begin
+          NextToken;
+          SetLength(Values, N);
+          NValues := 0;
+          while True do begin
+            if NValues >= N then
+              raise EIdentError.CreateFmt(SIndexIsOutOfArraySize, [NValues, Name]);
+            Values[NValues] := Expr(True);
+            MakeRValue(Values[NValues]);
+            Inc(NValues);
+            if PeekAtNextToken <> tkComma then
+              Break;
+            NextToken;
+          end;
+          NextTokenExpect([tkCloseBrace]);
+        end;
+      FIdentManager.DimVariable(Name, N, Scope, ReDim);
+      if ReDim and (NValues <> 0) then
+        Error('Initializers not allowed on #redim of existing array');
+      for I := 0 to NValues-1 do
+        FIdentManager.DefineVariable(Name, I, Values[I], Scope);
     finally
       //Free
     end;
@@ -1825,11 +1848,14 @@ begin
 end;
 
 procedure TProcCallContext.UpdateScope;
+var
+  ReDim: Boolean;
 begin
   if not FScopeUpdated then
   begin
     FPreproc.FIdentManager.BeginLocal;
-    FPreproc.FIdentManager.DimVariable(SLocal, 16, dsPrivate, False);
+    ReDim := False;
+    FPreproc.FIdentManager.DimVariable(SLocal, 16, dsPrivate, ReDim);
     FScopeUpdated := True;
   end;
 end;

+ 5 - 1
whatsnew.htm

@@ -38,7 +38,11 @@ For conditions of distribution and use, see <a href="http://www.jrsoftware.org/f
     <li>When paused on a breakpoint in the [Code] section the new "Debug Call Stack" view now shows the call stack.</li>
   </ul>
   </li>
-  <li>Inno Setup Preprocessor (ISPP) change: Added new predefined variable <tt>Tab</tt>.</li>
+  <li>Inno Setup Preprocessor (ISPP) changes:
+  <ul>
+    <li>Array variables declared with <tt>#dim</tt> can now be initialized directly, like <tt>#dim MyArray[3] {1, &apos;2&apos;, 3}</tt> for example.</li>
+    <li>Added new predefined variable <tt>Tab</tt>.</li>
+  </ul>
   <li>Pascal Scripting change: Added new <tt>Set8087CW</tt> and <tt>Get8087CW</tt> support functions.</li>
   <li>Some messages have been added in this version: (<a href="https://github.com/jrsoftware/issrc/commit/dfdf02aef168be458b64e77afb20ae53a5b4f2ec">View differences in Default.isl</a>).
   <ul>