delphi – 用FPC编写一个Scheme解释器:Allocation和Pointers
发布时间:2020-12-15 09:25:34 所属栏目:大数据 来源:网络整理
导读:作为一名历史学家,在第一阶段已经写了一个 Scheme interpreter in FPC转,对我来说是一个严肃的任务. :)我正在关注Peter Michaux的博客,who showed how to do it in C(还有一个 Ada的翻译,可能对Pascal有帮助). 从Michaux的工作中考虑C中的这两个函数(v 0.1)
作为一名历史学家,在第一阶段已经写了一个
Scheme interpreter in FPC转,对我来说是一个严肃的任务. :)我正在关注Peter Michaux的博客,who showed how to do it in C(还有一个
Ada的翻译,可能对Pascal有帮助).
从Michaux的工作中考虑C中的这两个函数(v 0.1): object *alloc_object(void) { object *obj; obj = malloc(sizeof(object)); if (obj == NULL) { fprintf(stderr,"out of memoryn"); exit(1); } return obj; } object *make_fixnum(long value) { object *obj; obj = alloc_object(); obj->type = FIXNUM; obj->data.fixnum.value = value; return obj; } 据我所知(只是C中的基本阅读知识),构造函数make_fixnum返回一个指向struct的指针(类型为fixnum的标记数据);对于构造的对象,必须分配内存(感谢@David Heffernan为他的point昨天). 这是我到目前为止对FPC的翻译,它编译时没有任何错误: program scheme; type TTag = (ScmFixnum); PScmObject = ^TScmObject; TScmObject = record case ScmObjectTag: TTag of ScmFixnum: (ScmObjectFixnum: integer); end; var Test: PScmObject = nil; procedure AllocateObject(x: PScmObject); begin new(x); end; function MakeFixnum(x: integer): PScmObject; var fixnum: PScmObject = nil; begin AllocateObject(fixnum); fixnum^.ScmObjectTag := ScmFixnum; fixnum^.ScmObjectFixnum := x; MakeFixnum := fixnum; end; begin Test := MakeFixnum(1); writeln(Test^.ScmObjectTag); writeln(Test^.ScmObjectFixnum); end. 然而…: $./test Runtime error 216 at $080480DD $080480DD $08048117 $08063873 我怀疑,我使用和引用指针有一个严重的缺陷. 非常感谢任何帮助我理解指针和记忆内容如何工作的人(也欢迎参考常见问题解答,论文等). 解决方法
您的AllocateObject函数是错误的.它在变量x中创建一个新对象,但它不会将创建的对象传递给调用函数,因为它是通过值调用的.如果您更改调用约定,它将起作用:
procedure AllocateObject(out x: PScmObject); begin new(x); end; 您可以看到如果您在调试器中查看fixnum变量,它保持为零. 与您的问题无关,我认为在翻译中使用记录并不是一个好主意.它很快就变成了一个管理噩梦的内存(至少在我接近20 kloc的时候写的翻译中发生了这种情况,我不得不更换记录如下:) 而不是你的记录 PScmObject = ^TScmObject; TScmObject = record case ScmObjectTag: TTag of ScmFixnum: (ScmObjectFixnum: integer); end; 你可以使用类,如: 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; 然后你可以轻松地创建它 var x: TScmObject; x := TScmObjectFixNum.create() ; if x.tag = scmfixnum (* or x is TScmObjectFixNum *) then ... x.scmfixnum ... x.free 如果您的方案实现中没有循环引用,您甚至可以使用接口.然后它被引用计数并自动释放: 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)! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |