The AllocateObject function is invalid. It creates a new object in the variable x, but does not pass the created object to the calling function, since it is called by the value. If you change the calling convention, it works:
procedure AllocateObject(out x: PScmObject); begin new(x); end;
You can see if you look at the fixnum variable in the debugger, it remains zero.
Not related to your question, I don't think it is a good idea to use records in the interpreter. It soon turns into a memory controlling a nightmare (at least this happened in the interpreter, which I wrote when it approached 20 kloc, and I had to replace the entries as follows :)
Instead of your entry
PScmObject = ^TScmObject; TScmObject = record case ScmObjectTag: TTag of ScmFixnum: (ScmObjectFixnum: integer); end;
you can use classes, for example:
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 easily create it 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 links in the schema implementation, you can even use interfaces. This link is then counted and automatically released:
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)!