program Project1;

{$H+}
{$IFDEF FPC}
  {$Mode ObjFPC}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

uses
  SysUtils, StrUtils;

type
  TMethodLogger = class(TInterfacedObject)
  private
    FName: string;
  public
    constructor Create(const AName: string);
    destructor Destroy; override;
  end;

var
  uIndent: integer = 0;

function LogMethod(const AName: string): IInterface;
begin
  Result := TMethodLogger.Create(AName);
end;

procedure Log(const AText: string);
var
  s: string;
begin
  s := DupeString(' ', uIndent);
  writeln(s + AText);
end;

procedure TryMe(i: integer);
begin
  LogMethod('TryMe');
  Log(Format('i = %d', [i]));
  Log(Format('%d is the answer to everything', [i]));
end;

{ TMethodLogger }

constructor TMethodLogger.Create(const AName: string);
var
  s: string;
begin
  inherited Create;
  FName := AName;
  s := DupeString(' ', uIndent);
  writeln(s + '>> ' + FName);
  inc(uIndent, 2);
end;

destructor TMethodLogger.Destroy;
var
  s: string;
begin
  dec(uIndent, 2);
  s := DupeString(' ', uIndent);
  writeln(s + '<< ' + FName);
  inherited;
end;


begin
  LogMethod('Main');
  Log('Here I am');
  TryMe(42);
  Log('We are reaching the end');
end.
