nielsAD / lape

Scripting engine with Pascal-like syntax for FPC and Delphi
118 stars 28 forks source link

abstraction problem/question... #98

Closed 3FLLC closed 7 years ago

3FLLC commented 7 years ago

// Include file 1: (in my parser Class is same as Record, nothing fancy!)

type
    BaseVideoDriver = Class
            Initialized:Boolean;
            CLS: private procedure of object;
            write: private procedure(Ch:Char) of object;
    end;

procedure BaseVideoDriver.Free;
var
    p:^BaseVideoDriver;
begin
    p := @Self;
    Dispose(p);
end;

procedure BaseVideoDriver.Init;
begin
    with Self do begin
            TMethod(@Free) := [@BaseVideoDriver.Free, @Self];
            TMethod(@CLS) := [@BaseVideoDriver.CLS, @Self];
            TMethod(@Write) := [@BaseVideoDriver.Write, @Self];
    end;
    Initialized:=true;
end;

procedure BaseVideoDriver.CLS;
begin
    ClrScr;
end;

procedure BaseVideoDriver.Write(Ch:Char);
begin
    Write(Ch);
end;

// include file 2:

type
    ANSIDriver = Class(BaseVideoDriver)
            fBuffer:String;
            inSequence:Boolean;
            //write: private procedure(S:String) of object; override;
    end;

procedure ANSIDriver.Init; override;
begin
    inherited;
    with Self do begin
            //TMethod(@write) := [@ANSIDriver.write, @Self];
    end;
end;

procedure ANSIDriver.ProcessBuffer(Ch:Char);
begin
    case Ch of

    else write('Unknown ANSI sequence.');
    end;
end;

procedure ANSIDriver.Write(Ch:Char); override;
begin
    if (not inSequence) and (ch=#27) then inSequence:=true
    else if inSequence then begin
            if ch='[' then break;
            if ((ch>#64) and (ch<#92)) or
                    ((ch>#96) and (ch<#123)) then begin
                    processBuffer(Ch);
                    inSequence:=false;
            end
            else fBuffer+=Ch;
    end
    else inherited(ch);
end;

procedure ANSIDriver.Write(S:String); overload;
begin
    For var loop:=1 to length(s) do Write(S[loop]);
end;
nielsAD commented 7 years ago

Your code looks okay, except for a few things. First, you have a field called write and a method called write on the same type. I think it's better to change one of the names to make sure you are calling the function you expect to be calling. Second, make sure the methods are defined before referencing them (forward the methods or place init behind the declarations).

I think the main issue you're running into is the name collision.

Here's an example that works:

type
  TTest = record
    a: Integer;
    Test: procedure of object;
  end;

  TTest2 = record(TTest)
    b: Integer;
  end;

procedure TTest.CallTest;
begin
  Test();
end;

procedure TTest.TestMe;
begin
  WriteLn('TTest.TestMe');
end;

procedure TTest.Init;
begin
  Test := @Self.TestMe;
end;

procedure TTest2.TestMe; override;
begin
  WriteLn('TTest2.TestMe');
end;

procedure TTest2.TestMe(a: Int32); overload;
begin
  WriteLn('TTest2.TestMe(', a, ')');
end;

procedure TTest2.Init; override;
begin
  inherited;
  Test := @TestMe;
end;

var
  x: TTest;
  y: TTest2;
begin
  x.Init();
  y.Init();
  x.TestMe();     // TTest.TestMe
  y.TestMe();     // TTest2.TestMe
  y.TestMe(123);  // TTest2.TestMe(123)
  x.CallTest();   // TTest.TestMe
  y.CallTest();   // TTest2.TestMe
end;