“Identifier Expected” or “Invalid Prototype” when

2020-01-26 11:01发布

问题:

So given this function, I get the error "Identifier Expected" on the GetRoot := ROOTPage.Values[0]; line. I expect it is telling me that the ROOTPage is not defined?

const
  DefaultRoot = 'C:\IAmGRoot';
Var
  ROOTPage : TInputQueryWizardPage;

procedure SetupRoot;
begin
  ROOTPage := CreateInputQueryPage(wpUserInfo,
    ExpandConstant('{cm:RootTitle}'), 
    ExpandConstant('{cm:RootInstructions}'),
    ExpandConstant('{cm:RootDescription}') + ' "' + DefaultRoot + '"'
    );

  ROOTPage.Add(ExpandConstant('{cm:SSRoot}') + ':', False);
  ROOTPage.Values[0] := ExpandConstant('{DefaultRoot}');

  // add SSROOT to path
end;

function GetRoot : string;
begin
  GetRoot := ROOTPage.Values[0];
end;

How should I interpret this error. What is an identifier in Pascal?

This page tells me that identifiers are variable names. Perhaps I need to expand the ROOTPage.Values[0] in some way since I am referencing an array from an Inno Setup object?

Or maybe I need to return the value differently. I saw one page on Pascal that said that you needed to avoid assigning to the function value on parameter less functions to avoid a recursive loop. Does this mean I should pass in a dummy value? or is there a different syntax? That page did not explain.

I secretly think my real issue is that I am not defining my function correctly... but well. That much compiles at least. This question could become: How do you handle a parameter-less function in Pascal?

I do not think Inno Setup is part of the issue, but I am working with Inno Setup in case that is important.

Update: It doesn't seem to be the array because this gets the same error:

const
  DefaultRoot = 'C:\IAmGRoot';

function GetRoot : string;
begin
  GetRoot := DefaultRoot;
end;

Update: This link has said that the function name can be replaced/ should be replaced with the key word Result such as the following code. I actually knew this, but the Inno Setup compiler does not recognize this as valid syntax. It then tells me my function is an invalid prototype.

function GetRoot : string;
begin
  Result := DefaultRoot;
end;

Update: If I do this I get "Invalid Prototype for GetRoot"

function GetRoot : boolean;
begin
  Result := False;
end;

Update for @Martin Prikryl:

Well I use it a few places but the typical use would be like this:

[Files]
Source: "C:\ValidPath\Release\*"; DestDir: "{app}\bin"; Components: DefinedComponent
Source: "C:\ValidPath\Deployment\*"; DestDir: "{code:GetRoot}\"; Flags: ignoreversion recursesubdirs; Components: DefinedComponent

回答1:

Identifier expected

Your code would be correct in a Pascal, but it does not compile in Pascal Script.

In Pascal, when you want to assign a return value of a function, you either assign the value to a "variable" with a name of the function or to Result variable.

So this is correct:

function GetRoot: string;
begin
  GetRoot := ROOTPage.Values[0];
end;

And this too (both are equivalent):

function GetRoot: string;
begin
  Result := ROOTPage.Values[0];
end;

In the Pascal Script, only the Result works. When you use the name of the function, you get the "Identifier expected."


Invalid prototype

You get this when the function is called from outside of the Code section and a specific parameter list/return value is required. But you didn't tell us, what you use the GetRoot function for.

There are two places, where you can use a custom function in Inno Setup:

  • Check parameter: For this the function must return a Boolean and take either no parameter or one parameter (the parameter type is determined by a value you provide in the Check parameter).

    function MyProgCheck(): Boolean;
    
    function MyDirCheck(DirName: String): Boolean;
    
  • Scripted Constants: The function must return a string and take one string parameter, even if no parameter is provided in the scripted constant. I assume this is your use case. If you do not need any parameter, just declare it, but do not use it:

    function GetRoot(Param: String): string;
    begin
      Result := ROOTPage.Values[0];
    end;