什么是原始的Forth运营商?

时间:2022-05-07 20:47:06

I'm interested in implementing a Forth system, just so I can get some experience building a simple VM and runtime.

我对实现Forth系统感兴趣,这样我就可以获得构建简单VM和运行时的一些经验。

When starting in Forth, one typically learns about the stack and its operators (DROP, DUP, SWAP, etc.) first, so it's natural to think of these as being among the primitive operators. But they're not. Each of them can be broken down into operators that directly manipulate memory and the stack pointers. Later one learns about store (!) and fetch (@) which can be used to implement DUP, SWAP, and so forth (ha!).

当在Forth开始时,人们通常首先了解堆栈及其运算符(DROP,DUP,SWAP等),因此将它们视为原始运算符之间是很自然的。但他们不是。它们中的每一个都可以分解为直接操作内存和堆栈指针的运算符。后来人们学习了存储(!)和获取(@),可用于实现DUP,SWAP等等(哈!)。

So what are the primitive operators? Which ones must be implemented directly in the runtime environment from which all others can be built? I'm not interested in high-performance; I want something that I (and others) can learn from. Operator optimization can come later.

那么原始运营商是什么?哪些必须直接在运行时环境中实现,从中可以构建所有其他环境?我对高性能不感兴趣;我想要一些我(和其他人)可以学习的东西。运营商优化可以在以后进行

(Yes, I'm aware that I can start with a Turing machine and go from there. That's a bit extreme.)

(是的,我知道我可以从图灵机启动并从那里开始。这有点极端。)

Edit: What I'm aiming for is akin to bootstrapping an operating system or a new compiler. What do I need do implement, at minimum, so that I can construct the rest of the system out of those primitive building blocks? I won't implement this on bare hardware; as an educational exercise, I'd write my own minimal VM.

编辑:我的目标是类似于引导操作系统或新编译器。我至少需要做什么才能实现,以便我可以用这些原始构建块构建系统的其余部分?我不会在裸硬件上实现它;作为一项教育活动,我会编写自己的最小虚拟机。

7 个解决方案

#1


This thread covers your exact question. Here is a soup-to-nuts implementation with complete documentation.

此主题涵盖您的确切问题。这是一个完整文档的汤到坚果实现。

I wrote a subroutine threaded Forth targeting 68K when I was in college. I defined the runtime environment and dictionary format, then wrote some C code that boot strapped a Macintosh application that loaded a default dictionary, populated some I/O vectors and got the code running. Then I took the Leo Brodie book Starting Forth and started implementing the basic dictionary in 68K assembly language. I started with arithmetic/logic words, then did control structures then word definition/manipulation words. My understanding is that at a minimum you need @, !, +, -, * and /. The rest can be implemented in terms of those, but that's like trying to write an entire graphics library based on SetPixel and GetPixel: it will work, but yikes, why?

我在大学期间编写了一个针对68K的子程序。我定义了运行时环境和字典格式,然后编写了一些C代码,它引导了一个加载了默认字典的Macintosh应用程序,填充了一些I / O向量并运行了代码。然后我拿了Leo Brodie的书“Starting Forth”,开始用68K汇编语言实现基本词典。我从算术/逻辑词开始,然后控制结构然后是字定义/操纵词。我的理解是,至少你需要@,!,+, - ,*和/。其余的可以用这些来实现,但这就像尝试编写基于SetPixel和GetPixel的整个图形库:它会工作,但是,为什么呢?

I enjoyed the process as there were some really interesting puzzles, like getting DOES> exactly right (and once I had a solid DOES> implementation, I was creating closures that turned into tiny, tiny amounts of code).

我很喜欢这个过程,因为有一些非常有趣的难题,比如让DOES>完全正确(而且一旦我有一个可靠的DOES>实现,我创建的闭包变成了微小的,少量的代码)。

#2


A long time ago, I had a book called "Threaded Interpretive Languages", published I think by Byte, that discussed how to implement a Forth-like language (I don't think they ever called it Forth) in Z80 assembly.

很久以前,我有一本名为“Threaded Interpretive Languages”的书,由Byte发表,我在Z80大会上讨论了如何实现类似Forth的语言(我认为它们从未称之为Forth)。

You may not have a Z80 handy, or want one, but the book might be instructive.

你可能没有Z80方便,或想要一个,但这本书可能是有益的。

#3


This post at comp.lang.forth lists a few "minimal Forths".

comp.lang.forth上的这篇文章列出了一些“最小的Forths”。

http://groups.google.com/group/comp.lang.forth/msg/10872cb68edcb526

Why do I know this? My brother, Mikael, wrote #3 and he also wrote a paper about making a "minimal Forth" (in Swedish, though). If I remember correctly he wanted to get a minimal set of operators that could be built in silicon.

为什么我知道这个?我的兄弟Mikael写了#3,他还写了一篇关于制作“最小Forth”的文章(虽然是瑞典文)。如果我没记错的话,他想获得一套可以用硅制造的最小的算子。

#4


I'm still not convinced the question is well-formed. For example, Plinth's instructions can be reduced; after all, * and / can be implemented in terms of + and -, but then '+' can be implemented in terms of a successor function (see the Peano axioms.) Which puts you into the neighborhood of a Turing machine. How do you know where to stop?

我仍然不相信这个问题很好。例如,Plinth的指令可以减少;毕竟,*和/可以用+和 - 来实现,但是'+'可以用后继函数来实现(参见Peano公理。)这会让你进入图灵机的附近。你怎么知道在哪里停下来?

#5


You might also want to take a look at Hans Bezemer's 4tH compiler.

您可能还想看看Hans Bezemer的4tH编译器。

#6


Which Forth implementation are you using that doesn't provide this information in the documentation? Given the nature of Forth, it might be implementation-dependent. There's a standard set of words in the dictionary, but whether they got there by assembly/C/whatever or by Forth shouldn't matter, since Forth is by definition a self-extensible language.

您使用哪种Forth实现不在文档中提供此信息?鉴于Forth的性质,它可能依赖于实现。在字典中有一组标准的单词,但是无论它们是通过汇编/ ​​C /无论是由Forth到达那里都不重要,因为Forth定义为一种自我扩展的语言。

#7


Contrary to what you say, generally DROP SWAP etc are considered basic Forth operations. The reason is that if you implement them using memory operations like you suggest, the overall system becomes more, not less complicated. Also there is no clear distinction in Forth between what is basic and what not. In the 80's a dictionary search would be basic, and coded in assembler for speed, while a modern linux hosted can afford to code that in so called high level. Also Forthers tend to routinely recode assembler words in high level, and high level words in assembler. I'm the author of ciforth and yourforth. It is possible to define <= as "> not" as I did in ciforth . But in yourforth I decided that having all of < <= > >= as similar, uniformly looking, small assembler routines was effectively simpler. That is a judgement call, and a matter of taste, certainly not a matter of principle.

与您所说的相反,通常DROP SWAP等被认为是基本的Forth操作。原因是如果你使用你建议的内存操作来实现它们,整个系统会变得更多,而不是更简单。在Forth和基础之间没有明显的区别。在80年代,字典搜索将是基本的,并以汇编语言编码以提高速度,而托管的现代Linux可以承担在所谓的高级别编码。 Forthers也倾向于常规地重新编译汇编语言中的高级汇编语言。我是ciforth和yourforth的作者。可以像在ciforth中那样定义<= as“> not”。但是在今后我决定让所有<=>> =相似,一致看,小的汇编程序实际上更简单。这是一种判断力,一种品味,当然不是原则问题。

In the context I interpret the question as: "What is a reasonable size for the number of primitive operations to arrive at a reasonable powerful Forth with a reasonable speed?" Clearly you are not interested in clever tricks to get rid of one assembler word at the expense of tremendous overhead as found in some of the threads discussing this subject.

在上下文中,我将这个问题解释为:“以合理的速度达到合理的强大Forth的原始操作数量的合理大小是多少?”很明显,你不会对巧妙的技巧感兴趣,以牺牲巨大的开销为代价来摆脱一个汇编词,正如在讨论这个主题的一些线程中所发现的那样。

Now you can look at a number of small Forth's like jonesforth yourforth eforth and conclude that mostly one arrives at around 50 to 100 primitives. Those Forth's are defined in assembler. If you want to define your primitives in c, python or Java , the situation is again different. Now for e.g. the above dictionary search you have a choice between c and Forth. Considerations that have nothing to do with language design come into play. You may be a prolific c-programmer, or you may insist on coding it in Forth because it is a learning project.

现在你可以看看像Jonesforth yourforth eforth这样的一些小Forth,并得出结论,大多数人到达大约50到100个原语。那些Forth是用汇编语言定义的。如果要在c,python或Java中定义基元,情况又会有所不同。现在,例如上面的字典搜索你可以选择c和Forth。与语言设计无关的考虑因素发挥作用。你可能是一个多产的程序员,或者你可能会坚持在Forth编码,因为它是一个学习项目。

#1


This thread covers your exact question. Here is a soup-to-nuts implementation with complete documentation.

此主题涵盖您的确切问题。这是一个完整文档的汤到坚果实现。

I wrote a subroutine threaded Forth targeting 68K when I was in college. I defined the runtime environment and dictionary format, then wrote some C code that boot strapped a Macintosh application that loaded a default dictionary, populated some I/O vectors and got the code running. Then I took the Leo Brodie book Starting Forth and started implementing the basic dictionary in 68K assembly language. I started with arithmetic/logic words, then did control structures then word definition/manipulation words. My understanding is that at a minimum you need @, !, +, -, * and /. The rest can be implemented in terms of those, but that's like trying to write an entire graphics library based on SetPixel and GetPixel: it will work, but yikes, why?

我在大学期间编写了一个针对68K的子程序。我定义了运行时环境和字典格式,然后编写了一些C代码,它引导了一个加载了默认字典的Macintosh应用程序,填充了一些I / O向量并运行了代码。然后我拿了Leo Brodie的书“Starting Forth”,开始用68K汇编语言实现基本词典。我从算术/逻辑词开始,然后控制结构然后是字定义/操纵词。我的理解是,至少你需要@,!,+, - ,*和/。其余的可以用这些来实现,但这就像尝试编写基于SetPixel和GetPixel的整个图形库:它会工作,但是,为什么呢?

I enjoyed the process as there were some really interesting puzzles, like getting DOES> exactly right (and once I had a solid DOES> implementation, I was creating closures that turned into tiny, tiny amounts of code).

我很喜欢这个过程,因为有一些非常有趣的难题,比如让DOES>完全正确(而且一旦我有一个可靠的DOES>实现,我创建的闭包变成了微小的,少量的代码)。

#2


A long time ago, I had a book called "Threaded Interpretive Languages", published I think by Byte, that discussed how to implement a Forth-like language (I don't think they ever called it Forth) in Z80 assembly.

很久以前,我有一本名为“Threaded Interpretive Languages”的书,由Byte发表,我在Z80大会上讨论了如何实现类似Forth的语言(我认为它们从未称之为Forth)。

You may not have a Z80 handy, or want one, but the book might be instructive.

你可能没有Z80方便,或想要一个,但这本书可能是有益的。

#3


This post at comp.lang.forth lists a few "minimal Forths".

comp.lang.forth上的这篇文章列出了一些“最小的Forths”。

http://groups.google.com/group/comp.lang.forth/msg/10872cb68edcb526

Why do I know this? My brother, Mikael, wrote #3 and he also wrote a paper about making a "minimal Forth" (in Swedish, though). If I remember correctly he wanted to get a minimal set of operators that could be built in silicon.

为什么我知道这个?我的兄弟Mikael写了#3,他还写了一篇关于制作“最小Forth”的文章(虽然是瑞典文)。如果我没记错的话,他想获得一套可以用硅制造的最小的算子。

#4


I'm still not convinced the question is well-formed. For example, Plinth's instructions can be reduced; after all, * and / can be implemented in terms of + and -, but then '+' can be implemented in terms of a successor function (see the Peano axioms.) Which puts you into the neighborhood of a Turing machine. How do you know where to stop?

我仍然不相信这个问题很好。例如,Plinth的指令可以减少;毕竟,*和/可以用+和 - 来实现,但是'+'可以用后继函数来实现(参见Peano公理。)这会让你进入图灵机的附近。你怎么知道在哪里停下来?

#5


You might also want to take a look at Hans Bezemer's 4tH compiler.

您可能还想看看Hans Bezemer的4tH编译器。

#6


Which Forth implementation are you using that doesn't provide this information in the documentation? Given the nature of Forth, it might be implementation-dependent. There's a standard set of words in the dictionary, but whether they got there by assembly/C/whatever or by Forth shouldn't matter, since Forth is by definition a self-extensible language.

您使用哪种Forth实现不在文档中提供此信息?鉴于Forth的性质,它可能依赖于实现。在字典中有一组标准的单词,但是无论它们是通过汇编/ ​​C /无论是由Forth到达那里都不重要,因为Forth定义为一种自我扩展的语言。

#7


Contrary to what you say, generally DROP SWAP etc are considered basic Forth operations. The reason is that if you implement them using memory operations like you suggest, the overall system becomes more, not less complicated. Also there is no clear distinction in Forth between what is basic and what not. In the 80's a dictionary search would be basic, and coded in assembler for speed, while a modern linux hosted can afford to code that in so called high level. Also Forthers tend to routinely recode assembler words in high level, and high level words in assembler. I'm the author of ciforth and yourforth. It is possible to define <= as "> not" as I did in ciforth . But in yourforth I decided that having all of < <= > >= as similar, uniformly looking, small assembler routines was effectively simpler. That is a judgement call, and a matter of taste, certainly not a matter of principle.

与您所说的相反,通常DROP SWAP等被认为是基本的Forth操作。原因是如果你使用你建议的内存操作来实现它们,整个系统会变得更多,而不是更简单。在Forth和基础之间没有明显的区别。在80年代,字典搜索将是基本的,并以汇编语言编码以提高速度,而托管的现代Linux可以承担在所谓的高级别编码。 Forthers也倾向于常规地重新编译汇编语言中的高级汇编语言。我是ciforth和yourforth的作者。可以像在ciforth中那样定义<= as“> not”。但是在今后我决定让所有<=>> =相似,一致看,小的汇编程序实际上更简单。这是一种判断力,一种品味,当然不是原则问题。

In the context I interpret the question as: "What is a reasonable size for the number of primitive operations to arrive at a reasonable powerful Forth with a reasonable speed?" Clearly you are not interested in clever tricks to get rid of one assembler word at the expense of tremendous overhead as found in some of the threads discussing this subject.

在上下文中,我将这个问题解释为:“以合理的速度达到合理的强大Forth的原始操作数量的合理大小是多少?”很明显,你不会对巧妙的技巧感兴趣,以牺牲巨大的开销为代价来摆脱一个汇编词,正如在讨论这个主题的一些线程中所发现的那样。

Now you can look at a number of small Forth's like jonesforth yourforth eforth and conclude that mostly one arrives at around 50 to 100 primitives. Those Forth's are defined in assembler. If you want to define your primitives in c, python or Java , the situation is again different. Now for e.g. the above dictionary search you have a choice between c and Forth. Considerations that have nothing to do with language design come into play. You may be a prolific c-programmer, or you may insist on coding it in Forth because it is a learning project.

现在你可以看看像Jonesforth yourforth eforth这样的一些小Forth,并得出结论,大多数人到达大约50到100个原语。那些Forth是用汇编语言定义的。如果要在c,python或Java中定义基元,情况又会有所不同。现在,例如上面的字典搜索你可以选择c和Forth。与语言设计无关的考虑因素发挥作用。你可能是一个多产的程序员,或者你可能会坚持在Forth编码,因为它是一个学习项目。