Menu

#206 Parser error with anonyous methods in unit initialization

v1.0 (example)
open-fixed
Parser (97)
5
2009-01-27
2009-01-27
Anonymous
No

unit Unit1;

interface

implementation
Default.FPrefix := function : String
begin
result := '';
end;
end.

This is valid code but parser claims it is not.

Discussion

  • Anthony Steele

    Anthony Steele - 2009-01-27

    I have verified the issue with the following code:

    unit TestAnonFunctionInInitialization;

    interface

    implementation

    Type
    TStringFunction = reference to function: string;

    var
    foo: TStringFunction;

    initialization

    foo := function: String
    begin
    result := 'fred';
    end;

    end.

     
  • Anthony Steele

    Anthony Steele - 2009-01-27
    • status: open --> open-fixed
     
  • Anthony Steele

    Anthony Steele - 2009-01-27

    A fix and test cases have been checked in, and will be in the next version.

     
  • Nobody/Anonymous

    hello, downloaded latest version and the test case you used is formating without error. However my code trows same error

    here is the full unit

    unit MeasuresEngine;

    interface

    uses
    Generics.Collections;

    type
    TPrefixSuffix = reference to function: string;
    TMeasureConvert = reference to function (Value: Variant): Variant;

    TMeasure = class
    private
    FName: String;
    FPrefix: TPrefixSuffix;
    FSuffix: TPrefixSuffix;
    FConvertFrom: TMeasureConvert;
    FConvertTo: TMeasureConvert;
    FFormat: String;
    procedure SetPrefix(const Value: TPrefixSuffix);
    procedure SetSuffix(const Value: TPrefixSuffix);
    constructor Create(Name: String); REINTRODUCE;
    procedure SetConvertFrom(const Value: TMeasureConvert);
    procedure SetConvertTo(const Value: TMeasureConvert);
    procedure SetFormat(const Value: String);
    public
    property Name: String READ FName;
    property Prefix: TPrefixSuffix READ FPrefix WRITE SetPrefix;
    property Suffix: TPrefixSuffix READ FSuffix WRITE SetSuffix;
    property Format: String READ FFormat WRITE SetFormat;
    property DefaultToMeasure: TMeasureConvert READ FConvertTo WRITE SetConvertTo;
    property MeasureToDefault: TMeasureConvert READ FConvertFrom WRITE SetConvertFrom;
    end;

    TMeasureChange = procedure(oldMeasure, newMeasure: TMeasure);

    function RegisterMeasure(MeasureName: String): TMeasure;
    procedure UnregisterMeasure(MeasureName: String);
    function GetMeasure(MeasureName: String): TMeasure;
    procedure SetCurrentMeasure(MeasureName: String);
    function GetCurrentMeasure: TMeasure;
    function EnumMeasures(Index: Cardinal): TMeasure;
    procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
    procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);

    implementation

    var
    Measures: TList<TMeasure>;
    Callbacks: TList<TMeasureChange>;
    Default, Current: TMeasure;

    procedure NotifyClients(Old, New: TMeasure);
    var
    Callback: TMeasureChange;
    begin
    for Callback in Callbacks do begin
    Callback(old, new);
    end;
    end;

    function RegisterMeasure(MeasureName: String): TMeasure;
    begin
    result := NIL;
    if not assigned(GetMeasure(MeasureName)) then
    result := TMeasure.Create(MeasureName);
    end;

    procedure UnregisterMeasure(MeasureName: String);
    var
    i: Integer;
    begin
    for i := 0 to Measures.Count - 1 do begin
    if Measures[i].Name = MeasureName then begin
    Measures[i].Destroy;
    Measures.Delete(i);
    end;
    end;
    end;

    function GetMeasure(MeasureName: String): TMeasure;
    var
    Measure: TMeasure;
    begin
    result := NIL;
    for Measure in Measures do begin
    if Measure.Name = MeasureName then
    exit(Measure);
    end;
    end;

    procedure SetCurrentMeasure(MeasureName: String);
    var
    Measure, OldMeasure: TMeasure;
    begin
    for Measure in Measures do begin
    if Measure.Name = MeasureName then begin
    if Measure <> Current then begin
    OldMeasure := Current;
    Current := Measure;
    NotifyClients(OldMeasure, Measure);
    end;
    exit;
    end;
    end;
    end;

    function GetCurrentMeasure: TMeasure;
    begin
    if Current = Default then
    result := NIL
    else
    result := Current;
    end;

    function EnumMeasures(Index: Cardinal): TMeasure;
    begin
    result := NIL;
    if Index < Cardinal(Measures.Count) then begin
    result := Measures[Index];
    end;
    end;

    procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
    begin
    Callbacks.Add(Callback);
    end;

    procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);
    begin
    Callbacks.Remove(Callback);
    end;

    { TMeasure }

    constructor TMeasure.Create(Name: String);
    begin
    inherited Create;
    FName := Name;
    end;

    procedure TMeasure.SetConvertFrom(const Value: TMeasureConvert);
    begin
    FConvertFrom := Value;
    end;

    procedure TMeasure.SetConvertTo(const Value: TMeasureConvert);
    begin
    FConvertTo := Value;
    end;

    procedure TMeasure.SetFormat(const Value: String);
    begin
    FFormat := Value;
    end;

    procedure TMeasure.SetPrefix(const Value: TPrefixSuffix);
    begin
    FPrefix := Value;
    end;

    procedure TMeasure.SetSuffix(const Value: TPrefixSuffix);
    begin
    FSuffix := Value;
    end;

    initialization
    Measures := TList<TMeasure>.Create;
    Callbacks := TList<TMeasureChange>.Create;
    Default := TMeasure.Create('Default');
    Default.FPrefix := function : String
    begin
    result := '';
    end;
    Default.FSuffix := Default.FPrefix;
    Default.FConvertFrom := function (Value: Variant) : Variant
    begin
    result := Value;
    end;
    Default.FConvertTo := Default.FConvertFrom;
    Current := Default;

    finalization
    Measures.Destroy;
    Callbacks.Destroy;
    Default.Destroy;
    end.

     
  • Anthony Steele

    Anthony Steele - 2009-01-28

    The issue now is that it fails if there is a statement after the anon function.
    I have checked in a fix to this and test case.

     
  • Nobody/Anonymous

    Yes now it works but for some reason it adds an extra empty line after the anonymous method. It could be because of my settings but didn't find a way to attach an file so if you can't reproduce it pls guide me how to attach files to my posts.

     
  • Nobody/Anonymous

    Just notice one more thing

    initialization
    Measures := TList<TMeasure>.Create;
    Callbacks := TList<TCallbackPair>.Create;
    Default := TMeasure.Create('Default');
    Default.FPrefix := function: String
    begin
    result := '';
    end;

    Default.FSuffix := Default.FPrefix;
    Default.FConvertFrom := function (Value: Variant): Variant
    begin
    result := Value;
    end;

    Default.FConvertTo := Default.FConvertFrom;
    Current := Default;
    finalization
    Measures.Destroy;
    Callbacks.Destroy;
    Default.Destroy;
    end.

    With this code it adds an empty line before the finalization clause. If I comment the code in initialization section there is no extra line.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.