Your AllocateObject function is wrong. It is creating a new object in the variable x, but it does not pass the created object to the calling function, since it is called by value. If you change the calling convention it works:
procedure AllocateObject(out x: PScmObject);
begin
new(x);
end;
You can see the if you look at the the fixnum variable in the debugger, it stayed nil.
Unrelated to your question, I do not think it is a good idea to use records in an interpreter. It turns soon in a memory managing nightmare (at least that happened in an interpreter I wrote when it came close to 20 kloc, and I had to replace records as follows:)
Instead of your record
PScmObject = ^TScmObject;
TScmObject = record
case ScmObjectTag: TTag of
ScmFixnum: (ScmObjectFixnum: integer);
end;
you can use classes, like:
TScmObject = class()
function Tag: TTag; virtual; abstract;
function Fixnum: integer; virtual; abstract;
end;
TScmObjectFixNum = class(TScmObject)
function Tag: TTag; override;
function Fixnum: integer; override;
private
value: integer;
end;
function TScmObjectFixNum.Tag: TTag;
begin
result := ScmFixnum;
end;
function TScmObjectFixNum.Fixnum: integer;
begin
result := value;
end;
Then you create it easily with
var x: TScmObject;
x := TScmObjectFixNum.create() ;
if x.tag = scmfixnum (* or x is TScmObjectFixNum *) then
... x.scmfixnum ...
x.free
If there are no circular references in your scheme implementation, you can even use interfaces. Then it is reference counted and automatically freed:
IScmObject = interface
function Tag: TTag;
function Fixnum: integer;
end;
TScmObject = class(TInterfacedObject, IScmObject)
function Tag: TTag; virtual; abstract;
function Fixnum: integer; virtual; abstract;
end;
TScmObjectFixNum = class(TScmObject)
function Tag: TTag; override;
function Fixnum: integer; override;
private
value: integer;
end;
var x: IScmObject;
x := TScmObjectFixNum.create() ;
if x.tag = scmfixnum (* or x is TScmObjectFixNum *) then
... x.scmfixnum ...
//x.free no longer necessary (or allowed)!