使用FPC编写Scheme解释器:递归数据结构

3
基本上,这是一个关于Pascal(FPC)中递归数据结构的问题。由于我想实现一个类似于SICP第4章所展示的Scheme解释器,因此这个问题可能也与Scheme相关。 :)
S表达式将被表示为带标签的数据。到目前为止,我已经构建了一个变量记录,它表示数字和对。希望代码可读性强而且自解释:
program scheme;

type
   TTag = (ScmFixnum, ScmPair);
   PScmObject = ^TScmObject;
   TScmObject = record
      case ScmObjectTag: TTag of
         ScmFixnum: (ScmObjectFixnum: integer);
         ScmPair: (ScmObjectCar, ScmObjectCdr: PScmObject);
      end;

var
   Test1: TScmObject;
   Test2: TScmObject;
   Test3: TScmObject;

function MakeFixnum(x: integer): TScmObject;
var
   fixnum: TScmObject;
begin
   fixnum.ScmObjectTag := ScmFixnum;
   fixnum.ScmObjectFixnum := x;
   MakeFixnum := fixnum;
end;

function MakePair(car, cdr: PScmObject): TScmObject;
var
   pair: TScmObject;
begin
   pair.ScmObjectTag := ScmPair;
   pair.ScmObjectCar := car;
   pair.ScmObjectCdr := cdr;
   MakePair := pair;
end;

begin
   Test1 := MakeFixnum(7);
   writeln('Test1, Tag: ', Test1.ScmObjectTag,
           ', Content: ', Test1.ScmObjectFixnum);
   Test2 := MakeFixnum(9);
   writeln('Test2, Tag: ', Test2.ScmObjectTag,
           ', Content: ', Test2.ScmObjectFixnum);
   Test3 := MakePair(Test1, Test2);
end.

然而,编译代码会产生以下错误:
$ fpc scheme.pas
(...)
Compiling scheme.pas
scheme.pas(43,34) Error: Incompatible type for arg no. 2: Got "TScmObject", expected "PScmObject"
scheme.pas(45) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted

很明显在函数MakePair中存在错误,但我还不明白到底错在哪里。感谢任何帮助 :)
2个回答

7

MakePair函数定义如下:

function MakePair(car, cdr: PScmObject): TScmObject;

请注意,它接收两个类型为PScmObject的指针。您可以像这样调用它:
MakePair(Test1, Test2);

但是Test1Test2的类型为TScmObject。因此传递的实际参数不兼容,正如编译器所说。

您需要传递这些记录的指针:

MakePair(@Test1, @Test2);

从长远来看,您需要小心这些记录的生命周期。您需要在堆上分配,并且如果没有垃圾收集,我怀疑您会进入一个痛苦的世界,试图跟踪谁拥有这些记录。也许您可以考虑使用接口引用计数来管理生命周期。


4
该过程需要一个指向记录的指针,而不是记录本身。
您可以在调用点使用“@”(at)运算符,即“即时创建”指向记录的指针,从而满足编译器类型检查:
begin
   Test1 := MakeFixnum(7);
   writeln('Test1, Tag: ', Test1.ScmObjectTag,
           ', Content: ', Test1.ScmObjectFixnum);
   Test2 := MakeFixnum(9);
   writeln('Test2, Tag: ', Test2.ScmObjectTag,
           ', Content: ', Test2.ScmObjectFixnum);
   Test3 := MakePair(@Test1, @Test2);
end.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接