Created `quick-start.md` to hold the FAQ 0.0 content. Used `sgit(1)` to change: * faq.html#enter ==> quick-start.html#enter * faq.html#enter_questions ==> quick-start.html#enter_questions * faq.html#step_0 ==> quick-start.html#step_0 * faq.html#step_1 ==> quick-start.html#step_1 * faq.html#step_2 ==> quick-start.html#step_2 * faq.html#register ==> quick-start.html#register * faq.html#step_3 ==> quick-start.html#step_3 * faq.html#step_4 ==> quick-start.html#step_4 * faq.html#step_5 ==> quick-start.html#step_5 * faq.html#step_6 ==> quick-start.html#step_6 * faq.html#step_7 ==> quick-start.html#step_7 * faq.html#step_submit ==> quick-start.html#step_submit Via: ```sh sgit -e 's/faq\.html#enter/quick-start.html#enter/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#enter_questions/quick-start.html#enter_questions/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_0/quick-start.html#step_0/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_1/quick-start.html#step_1/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_2/quick-start.html#step_2/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#register/quick-start.html#register/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_3/quick-start.html#step_3/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_4/quick-start.html#step_4/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_5/quick-start.html#step_5/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_6/quick-start.html#step_6/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_7/quick-start.html#step_7/g' '*.md' '*.hdr' 'inc/*.html' sgit -e 's/faq\.html#step_submit/quick-start.html#step_submit/g' '*.md' '*.hdr' 'inc/*.html' ``` The former FAQ 0.0 section in `faq.html` now just refers to `quick-start.html`. Modified menu and non-JS menu so that "Enter the IOCCC" refers to `quick-start.html`. Changed `bin/gen-top-html.sh` VERSION from "1.4.10 2024-11-23" to "1.4.11 2025-01-09". Performed `make www` on macOS to complete the above.
1212 lines
49 KiB
HTML
1212 lines
49 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||
|
||
<!-- END: this line ends content from: inc/top.default.html -->
|
||
<!-- START: this line starts content from: inc/head.default.html -->
|
||
|
||
<head>
|
||
<link rel="stylesheet" href="../../ioccc.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||
<title>The International Obfuscated C Code Contest</title>
|
||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||
<meta name="description" content="buzzard.2.design.md for 1992/buzzard.2">
|
||
<meta name="keywords" content="IOCCC, 1992/buzzard.2, buzzard.2.design.md">
|
||
</head>
|
||
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
|
||
<!-- END: this line ends content from: inc/head.default.html -->
|
||
|
||
<!-- -->
|
||
<!-- This web page was formed via the tool: bin/gen-other-html.sh -->
|
||
<!-- The content of main section of this web page came from: 1992/buzzard.2/buzzard.2.design.md -->
|
||
<!-- -->
|
||
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1992/buzzard.2/buzzard.2.design.md !!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1992/buzzard.2/buzzard.2.design.md !!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1992/buzzard.2/buzzard.2.design.md !!! -->
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
|
||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||
|
||
<!-- START: this line starts content from: inc/body.default.html -->
|
||
|
||
<body>
|
||
|
||
<!-- END: this line ends content from: inc/body.default.html -->
|
||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||
|
||
<div class="theader">
|
||
<nav class="topbar">
|
||
<div class="container">
|
||
<div class="logo">
|
||
<a href="../../index.html" class="logo-link">
|
||
IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="topbar-items">
|
||
<div class="item">
|
||
<span class="item-header">
|
||
Entries
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../years.html" class="sub-item-link">
|
||
Winning entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../authors.html" class="sub-item-link">
|
||
Winning authors
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../location.html" class="sub-item-link">
|
||
Location of authors
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../bugs.html" class="sub-item-link">
|
||
Bugs and (mis)features
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||
Fixing entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||
Updating author info
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
Status
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../news.html" class="sub-item-link">
|
||
News
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../status.html" class="sub-item-link">
|
||
Contest status
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../next/index.html" class="sub-item-link">
|
||
Rules and guidelines
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../markdown.html" class="sub-item-link">
|
||
Markdown guidelines
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../SECURITY.html" class="sub-item-link">
|
||
Security policy
|
||
</a>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
FAQ
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html" class="sub-item-link">
|
||
Frequently Asked Questions
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../quick-start.html#enter" class="sub-item-link">
|
||
Enter the IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#compiling" class="sub-item-link">
|
||
Compiling entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#running_entries" class="sub-item-link">
|
||
Running entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#help" class="sub-item-link">
|
||
How to help
|
||
</a>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
About
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../index.html" class="sub-item-link">
|
||
Home page
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../about.html" class="sub-item-link">
|
||
About the IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../judges.html" class="sub-item-link">
|
||
The Judges
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||
Thanks for the help
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../contact.html" class="sub-item-link">
|
||
Contact us
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="header-mobile-menu">
|
||
<noscript>
|
||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||
Please Enable JavaScript
|
||
</a>
|
||
</noscript>
|
||
|
||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||
<img
|
||
src="../../png/hamburger-icon-open.png"
|
||
alt="hamburger style menu icon - open state"
|
||
width=48
|
||
height=48>
|
||
</button>
|
||
|
||
<button id="header-close-menu-button" class="hide-content">
|
||
<img
|
||
src="../../png/hamburger-icon-closed.png"
|
||
alt="hamburger style menu icon - closed state"
|
||
width=48
|
||
height=48>
|
||
</button>
|
||
|
||
<div id="mobile-menu-panel" class="hide-content">
|
||
<div class="mobile-menu-container">
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
Entries
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../years.html">
|
||
Winning entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../authors.html">
|
||
Winning authors
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../location.html">
|
||
Location of authors
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||
Bugs and (mis)features
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||
Fixing entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||
Updating author info
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||
Thanks for the help
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
|
||
<div class="mobile-menu-item">
|
||
Status
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../news.html">
|
||
News
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../status.html">
|
||
Contest status
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../next/index.html">
|
||
Rules and guidelines
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../markdown.html">
|
||
Markdown guidelines
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../SECURITY.html">
|
||
Security policy
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
FAQ
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html">
|
||
Frequently Asked Questions
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../quick-start.html#enter">
|
||
Enter the IOCCC
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#compiling">
|
||
Compiling entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#running_entries">
|
||
Running entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#help">
|
||
How to help
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
About
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../index.html">
|
||
Home page
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../about.html">
|
||
About the IOCCC
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../judges.html">
|
||
The Judges
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../contact.html">
|
||
Contact us
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||
|
||
headerOpenMenuButton.addEventListener("click", () => {
|
||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||
headerOpenMenuButton.classList.add("hide-content");
|
||
|
||
headerCloseMenuButton.classList.remove("hide-content");
|
||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||
|
||
mobileMenuPanel.classList.remove("hide-content");
|
||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||
});
|
||
|
||
headerCloseMenuButton.addEventListener("click", () => {
|
||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||
headerCloseMenuButton.classList.add("hide-content");
|
||
|
||
mobileMenuPanel.classList.add("hide-content");
|
||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||
|
||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||
headerOpenMenuButton.classList.remove("hide-content");
|
||
});
|
||
</script>
|
||
|
||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||
<!-- START: this line starts content from: inc/header.default.html -->
|
||
|
||
<div class="header">
|
||
<a href="../../2011/zucker/index.html">
|
||
<img src="../../png/ioccc.png"
|
||
alt="IOCCC image by Matt Zucker"
|
||
width=300
|
||
height=110>
|
||
</a>
|
||
<h1>The International Obfuscated C Code Contest</h1>
|
||
<h2>buzzard.2.design.html for 1992/buzzard.2</h2>
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/header.default.html -->
|
||
<!-- START: this line starts content from: inc/navbar.up2index.html -->
|
||
|
||
<div class="navbar">
|
||
<a class="Left" href="index.html">↑ jump to 1992/buzzard.2/index.html ↑</a>
|
||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F1992%2Fbuzzard.2%2Fbuzzard.2.design.html">✓</a>
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/navbar.up2index.html -->
|
||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||
|
||
<div class="content" id="content">
|
||
|
||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||
|
||
<!-- BEFORE: 1st line of markdown file: 1992/buzzard.2/buzzard.2.design.md -->
|
||
<h1 id="first-third-almost-forth">FIRST & THIRD (almost FORTH)</h1>
|
||
<p>FORTH is a language mostly familiar to users of “small” machines.
|
||
FORTH programs are small because they are interpreted–a function
|
||
call in FORTH takes two bytes. FORTH is an extendable language–
|
||
built-in primitives are indistinguishable from user-defined
|
||
<em>words</em>. FORTH interpreters are small because much of the system
|
||
can be coded in FORTH–only a small number of primitives need to
|
||
be implemented. Some FORTH interpreters can also compile defined
|
||
words into machine code, resulting in a fast system.</p>
|
||
<p>FIRST is an incredibly small language which is sufficient for
|
||
defining the language THIRD, which is mostly like FORTH. There are
|
||
some differences, and THIRD is probably just enough like FORTH for
|
||
those differences to be disturbing to regular FORTH users.</p>
|
||
<p>The only existing FIRST interpreter is written in obfuscated C,
|
||
and rings in at under 800 bytes of source code, although through
|
||
deletion of both whitespace and obfuscation it can be brought to about 650
|
||
bytes.</p>
|
||
<p>This document FIRST defines the FIRST environment and primitives,
|
||
with relevant design decision explanations. It secondly documents
|
||
the general strategies we will use to implement THIRD. The THIRD
|
||
section demonstrates how the complete THIRD system is built up
|
||
using FIRST.</p>
|
||
<h2 id="section-1-first">Section 1: FIRST</h2>
|
||
<h3 id="environment">Environment</h3>
|
||
<p>FIRST implements a virtual machine. The machine has three chunks
|
||
of memory: “main memory”, “the stack”, and “string storage”. When
|
||
the virtual machine wishes to do random memory accesses, they come
|
||
out of main memory–it cannot access the stack or string storage.</p>
|
||
<p>The stack is simply a standard LIFO data structure that is used
|
||
implicitly by most of the FIRST primitives. The stack is made up
|
||
of <code>int</code>s, whatever size they are on the host machine.</p>
|
||
<p>String storage is used to store the names of built-in and defined
|
||
primitives. Separate storage is used for these because it allows
|
||
the C code to use C string operations, reducing C source code size.</p>
|
||
<p>Main memory is a large array of <code>int</code>s. When we speak of
|
||
addresses, we actually mean indices into main memory. Main memory
|
||
is used for two things, primarily: the return stack and the dictionary.</p>
|
||
<p>The return stack is a LIFO data structure, independent of
|
||
the above-mentioned “stack”, which is used by FIRST to keep
|
||
track of function call return addresses.</p>
|
||
<p>The dictionary is a list of words. Each word contains a header
|
||
and a data field. In the header is the address of the previous word,
|
||
an index into the string storage indicating where the name of this
|
||
word is stored, and a “code pointer”. The code pointer is simply
|
||
an integer which names which “machine-language-primitive” implements
|
||
this instruction. For example, for defined words the code pointer
|
||
names the “run some code” primitive, which pushes the current program
|
||
counter onto the return stack and sets the counter to the address of
|
||
the data field for this word.</p>
|
||
<p>There are several important pointers into main memory. There is
|
||
a pointer to the most recently defined word, which is used to start
|
||
searches back through memory when compiling words. There is a pointer
|
||
to the top of the return stack. There is a pointer to the current
|
||
end of the dictionary, used while compiling.</p>
|
||
<p>For the last two pointers, namely the return stack pointer and
|
||
the dictionary pointer, there is an important distinction: the pointers
|
||
themselves are stored in main memory (in <code>FIRST</code>’s main memory). This
|
||
is critical, because it means FIRST programs can get at them without
|
||
any further primitives needing to be defined.</p>
|
||
<h3 id="instructions">Instructions</h3>
|
||
<p>There are two kinds of FIRST instructions, normal instructions and
|
||
immediate instructions. Immediate instructions do something significant
|
||
when they are used. Normal instructions compile a pointer to their
|
||
executable part onto the end of the dictionary. As we will see, this
|
||
means that by default FIRST simply compiles things.</p>
|
||
<h4 id="integer-operations">Integer Operations</h4>
|
||
<pre><code> SYMBOL NAME FUNCTION
|
||
|
||
- binary minus pop top 2 elements of stack, subtract, push
|
||
|
||
* multiply pop top 2 elements of stack, multiply, push
|
||
|
||
/ divide pop top 2 elements of stack, divide, push
|
||
|
||
<0 less than 0 pop top element of stack, push 1 if < 0 else 0</code></pre>
|
||
<p>Note that we can synthesize addition and negation from binary minus,
|
||
but we cannot synthesize a time efficient divide or multiply from it.
|
||
<code><0</code> is synthesize-able, but only in a non-portable way.</p>
|
||
<h4 id="memory-operations">Memory Operations</h4>
|
||
<pre><code> SYMBOL NAME FUNCTION
|
||
|
||
@ fetch pop top of stack, treat as address to push contents of
|
||
|
||
! store top of stack is address, 2nd is value; store to memory
|
||
and pop both off the stack</code></pre>
|
||
<h4 id="inputoutput-operations">Input/Output Operations</h4>
|
||
<pre><code> NAME FUNCTION
|
||
|
||
echo output top of stack through C's putchar()
|
||
|
||
key push C's getchar() onto top of stack
|
||
|
||
_read read a space-delimited word, find it in the
|
||
dictionary, and compile a pointer to
|
||
that word's code pointer onto the
|
||
current end of the dictionary</code></pre>
|
||
<p>Although <code>_read</code> could be synthesized from key, we need <code>_read</code> to be able
|
||
to compile words to be able to start any syntheses.</p>
|
||
<h4 id="execution-operations">Execution Operations</h4>
|
||
<pre><code> NAME FUNCTION
|
||
|
||
exit leave the current function: pop the return stack
|
||
into the program counter</code></pre>
|
||
<h4 id="immediate-compilation-operations">Immediate (compilation) Operations</h4>
|
||
<pre><code> SYMBOL NAME FUNCTION
|
||
|
||
: define read in the next space-delimited word, add it to
|
||
the end of our string storage, and generate
|
||
a header for the new word so that when it
|
||
is typed it compiles a pointer to itself
|
||
so that it can be executed.
|
||
|
||
immediate immediate when used immediately after a name following a ':',
|
||
it makes the word being defined run whenever
|
||
it is typed.</code></pre>
|
||
<p><code>:</code> cannot be synthesized, because we could not synthesize anything.
|
||
<code>immediate</code> has to be an immediate operation, so it could not be
|
||
synthesized unless by default operations were immediate; but that
|
||
would preclude our being able to do any useful compilation.</p>
|
||
<h4 id="stack-operations">Stack Operations</h4>
|
||
<pre><code> NAME FUNCTION
|
||
|
||
pick pop top of stack, use as index into stack and copy up
|
||
that element</code></pre>
|
||
<p>If the data stack were stored in main memory, we could synthesize <code>pick</code>;
|
||
but putting the stack and stack pointer in main memory would significantly
|
||
increase the C source code size.</p>
|
||
<p>There are three more primitives, but they are “internal only”–
|
||
they have no names and no dictionary entries. The first is
|
||
<code>pushint</code>. It takes the next integer out of the instruction stream
|
||
and pushes it on the stack. This could be synthesized, but probably
|
||
not without using integer constants. It is generated by <code>_read</code> when
|
||
the input is not a known word. The second is <code>compile me</code>. When
|
||
this instruction is executed, a pointer to the word’s data field is
|
||
appended to the dictionary. The third is <code>run me</code>–the word’s data
|
||
field is taken to be a stream of pointers to words, and is executed.</p>
|
||
<p>One last note about the environment: FIRST builds a very small
|
||
word internally that it executes as its main loop. This word calls
|
||
<code>_read</code> and then calls itself. Each time it calls itself, it uses
|
||
up a word on the return stack, so it will eventually trash things.
|
||
This is discussed some more in section 2.</p>
|
||
<p>Here’s a handy summary of all the FIRST words:</p>
|
||
<pre><code> WORD DESCRIPTION
|
||
|
||
- * / binary integer operations on the stack
|
||
<0 is top of stack less than 0?
|
||
@ ! read from or write to memory
|
||
echo key output or input one character
|
||
_read read a word from input and compile a pointer to it
|
||
exit stop running the current function
|
||
: compile the header of a definition
|
||
immediate modify the header to create an immediate word</code></pre>
|
||
<p>Here is a sample FIRST program. I’m assuming you’re using
|
||
the ASCII character set. FIRST does not depend upon ASCII, but
|
||
since FIRST has no syntax for character constants, one normally has
|
||
to use decimal values. This can be avoided using <code>getchar(3)</code>, though.
|
||
Oh. One other odd thing. FIRST initially builds its symbol table
|
||
by calling <code>:</code> several times, so it needs to get the names of the base
|
||
symbols as its first 13 words of input. You could even name them
|
||
differently if you wanted.</p>
|
||
<p>These FIRST programs have FORTH comments in them: they are contained
|
||
inside parentheses. FIRST programs cannot have FORTH comments; but I need
|
||
some device to indicate what’s going on. (THIRD programs are an entirely
|
||
different subject.)</p>
|
||
<pre><code> ( Our first line gives the symbols for the built-ins )
|
||
: immediate _read @ ! - * / <0 exit echo key _pick
|
||
|
||
( now we define a simple word that will print out a couple characters )
|
||
|
||
: L ( define a word named 'L' )
|
||
108 echo ( output an ascii 'l' )
|
||
exit
|
||
|
||
: hello ( define a word named 'hello')
|
||
72 echo ( output an ascii 'H' )
|
||
101 echo ( output an ascii 'e' )
|
||
111 ( push ascii 'o' onto the stack )
|
||
L L ( output two ascii 'l's )
|
||
echo ( output the 'o' we pushed on the stack before )
|
||
10 echo ( print a newline )
|
||
exit ( stop running this routine )
|
||
|
||
: test immediate ( define a word named 'test' that runs whenever typed )
|
||
hello ( call hello )
|
||
exit
|
||
|
||
test
|
||
|
||
( The result of running this program should be:
|
||
Hello
|
||
)</code></pre>
|
||
<h2 id="section-2-motivating-third">Section 2: Motivating THIRD</h2>
|
||
<p>What is missing from FIRST? There are a large number of
|
||
important primitives that aren’t implemented, but which are
|
||
easy to implement. <code>drop</code>, which throws away the top of the
|
||
stack, can be implemented as <code>{ 0 * + }</code> – that is, multiply
|
||
the top of the stack by <code>0</code> (which turns the top of the stack
|
||
into a <code>0</code>), and then add the top two elements of the stack.</p>
|
||
<p><code>dup</code>, which copies the top of the stack, can be easily
|
||
implemented using temporary storage locations. Conveniently,
|
||
FIRST leaves memory locations <code>3</code>, <code>4</code>, and <code>5</code> unused. So we can
|
||
implement <code>dup</code> by writing the top of stack into <code>3</code>, and then
|
||
reading it out twice: <code>{ 3 ! 3 @ 3 @ }</code>.</p>
|
||
<p>We will never use the FIRST primitive <code>pick</code> in building THIRD,
|
||
just to show that it can be done; <code>pick</code> is only provided because
|
||
<code>pick</code> itself cannot be built out of the rest of <code>FIRST</code>’s building
|
||
blocks.</p>
|
||
<p>So, instead of worrying about stack primitives and the
|
||
like, what else is missing from FIRST? We get recursion, but
|
||
no control flow–no conditional operations. We cannot at the
|
||
moment write a looping routine which terminates.</p>
|
||
<p>Another glaring dissimilarity between FIRST and FORTH is
|
||
that there is no “command mode”–you cannot be outside of a
|
||
<code>:</code> definition and issue some straight commands to be executed.
|
||
Also, as we noted above, we cannot do comments.</p>
|
||
<p>FORTH also provides a system for defining new data types,
|
||
using the words (in one version of FORTH) <code>builds and does</code>.
|
||
We would like to implement these words as well.</p>
|
||
<p>As the highest priority thing, we will build control flow
|
||
structures first. Once we have control structures, we can
|
||
write recursive routines that terminate, and we are ready to
|
||
tackle tasks like parsing, and the building of a command mode.</p>
|
||
<p>By the way, location <code>0</code> holds the dictionary pointer, location
|
||
<code>1</code> holds the return stack pointer, and location <code>2</code> should always
|
||
be <code>0</code>–it’s a fake dictionary entry that means <code>pushint</code>.</p>
|
||
<h2 id="section-3-building-third">Section 3: Building THIRD</h2>
|
||
<p>In this section we’ll eventually have real comments.</p>
|
||
<p>The first thing we have to do is give the symbols for our built-ins.</p>
|
||
<pre><code> : immediate _read @ ! - * / < exit echo key _pick</code></pre>
|
||
<p>Next we want to be mildly self commenting, so we define the word <code>r</code> to push
|
||
the <em>address of the return stack pointer</em> onto the stack–NOT the value of the
|
||
return stack pointer. (In fact, when we run <code>r</code>, the value of the return stack
|
||
pointer is temporarily changed.)</p>
|
||
<pre><code> : r 1 exit</code></pre>
|
||
<p>Next, we’re currently executing a short loop that contains <code>_read</code> and
|
||
recursion, which is slowly blowing up the return stack. So let’s define a new
|
||
word, from which you can never return. What it does is drops the top value off
|
||
the return stack, calls <code>_read</code>, then calls itself. Because it kills the top of
|
||
the return stack, it can recurse indefinitely.</p>
|
||
<pre><code> : ]
|
||
r @ Get the value of the return stack pointer
|
||
1 - Subtract one
|
||
r ! Store it back into the return stack pointer
|
||
_read Read and compile one word
|
||
] Start over</code></pre>
|
||
<p>Notice that we don’t need to exit, since we never come back. Also, it’s
|
||
possible that an immediate word may get run during <code>_read</code>, and that <code>_read</code>
|
||
will never return!</p>
|
||
<p>Now let’s get compile running.</p>
|
||
<pre><code> : main immediate ]
|
||
main</code></pre>
|
||
<p>Next off, I’m going to do this the easy but non-portable way, and put some
|
||
character constant definitions in. I wanted them at the top of the file, but
|
||
that would have burned too much of the return stack.</p>
|
||
<pre><code> : '"' 34 exit
|
||
: ')' 41 exit
|
||
: '\n' 10 exit
|
||
: 'space' 32 exit
|
||
: '0' 48 exit
|
||
: '-' 45 exit
|
||
|
||
: cr '\n' echo exit</code></pre>
|
||
<p>Next, we want to define some temporary variables for locations <code>3</code>, <code>4</code>, and
|
||
<code>5</code>, since this’ll make our code look clearer.</p>
|
||
<pre><code> : _x 3 @ exit
|
||
: _x! 3 ! exit
|
||
: _y 4 @ exit
|
||
: _y! 4 ! exit</code></pre>
|
||
<p>OK. Now, we want to make THIRD look vaguely like FORTH,
|
||
so we’re going to define <code>;</code>. What <code>;</code> ought to do is
|
||
terminate a compilation, and turn control over to the
|
||
command-mode handler. We don’t have one, so all we want
|
||
<code>;</code> to do for now is compile <code>exit</code> at the end of the
|
||
current word. To do this we’ll need several other words.</p>
|
||
<p>Swap by writing out the top two elements into temps, and
|
||
then reading them back in the other order.</p>
|
||
<pre><code> : swap _x! _y! _x _y exit</code></pre>
|
||
<p>Take another look and make sure you see why that works,
|
||
since it LOOKS like I’m reading them back in the same
|
||
order–in fact, it not only looks like it, but I AM!</p>
|
||
<p>Addition might be nice to have. To add, we need to
|
||
negate the top element of the stack, and then subtract.
|
||
To negate, we subtract from <code>0</code>.</p>
|
||
<pre><code> : +
|
||
0 swap -
|
||
-
|
||
exit</code></pre>
|
||
<p>Create a copy of the top of stack.</p>
|
||
<pre><code> : dup _x! _x _x exit</code></pre>
|
||
<p>Get a mnemonic name for our dictionary pointer–we need
|
||
to compile stuff, so it goes through this.</p>
|
||
<pre><code> : h 0 exit</code></pre>
|
||
<p>We’re going to need to advance that pointer, so let’s
|
||
make a generic pointer-advancing function.
|
||
Given a pointer to a memory location, increment the value
|
||
at that memory location.</p>
|
||
<pre><code> : inc
|
||
dup @ Get another copy of the address, and get the value
|
||
so now we have value, address on top of stack.
|
||
1 + Add one to the value
|
||
swap Swap to put the address on top of the stack
|
||
! exit Write it to memory</code></pre>
|
||
<p><code>,</code> is a standard FORTH word. It should write the top of
|
||
stack into the dictionary, and advance the pointer</p>
|
||
<pre><code> : ,
|
||
h @ Get the value of the dictionary pointer
|
||
! Write the top of stack there
|
||
h inc And increment the dictionary pointer
|
||
exit</code></pre>
|
||
<p><code>'</code> is a standard FORTH word. It should push the address
|
||
of the word that follows it onto the stack. We could
|
||
do this by making <code>'</code> immediate, but then it’d need to
|
||
parse the next word. Instead, we compile the next word
|
||
as normal. When <code>'</code> is executed, the top of the return
|
||
stack will point into the instruction stream immediately
|
||
after the <code>'</code>. We push the word there, and advance the
|
||
return stack pointer so that we don’t execute it.</p>
|
||
<pre><code> : '
|
||
r @ Get the address of the top of return stack
|
||
We currently have a pointer to the top of return stack
|
||
@ Get the value from there
|
||
We currently have a pointer to the instruction stream
|
||
dup Get another copy of it--the bottom copy will stick
|
||
around until the end of this word
|
||
1 + Increment the pointer, pointing to the NEXT instruction
|
||
r @ ! Write it back onto the top of the return stack
|
||
We currently have our first copy of the old pointer
|
||
to the instruction stream
|
||
@ Get the value there--the address of the "next word"
|
||
exit</code></pre>
|
||
<p>Now we’re set. <code>;</code> should be an immediate word that pushes
|
||
the address of <code>exit</code> onto the stack, then writes it out.</p>
|
||
<pre><code> : ; immediate
|
||
' exit Get the address of exit
|
||
, Compile it
|
||
exit And we should return</code></pre>
|
||
<p>Now let’s test out <code>;</code> by defining a useful word:</p>
|
||
<pre><code> : drop 0 * + ;</code></pre>
|
||
<p>Since we have <code>inc</code>, we ought to make <code>dec</code>:</p>
|
||
<pre><code> : dec dup @ 1 - swap ! ;</code></pre>
|
||
<p>Our next goal, now that we have <code>;</code>, is to implement
|
||
<code>if-then</code>. To do this, we’ll need to play fast and
|
||
loose with the return stack, so let’s make some
|
||
words to save us some effort.</p>
|
||
<p>First we want a word that pops off the top of the normal
|
||
stack and pushes it on top of the return stack. We’ll
|
||
call this <code>tor</code>, for TO-Return-stack. It sounds easy,
|
||
but when <code>tor</code> is running, there’s an extra value on the
|
||
return stack–<code>tor</code>’s return address! So we have to pop
|
||
that off first… We better just bite the bullet and
|
||
code it out–but we can’t really break it into smaller
|
||
words, because that’ll trash the return stack.</p>
|
||
<pre><code> : tor
|
||
r @ @ Get the value off the top of the return stack
|
||
swap Bring the value to be pushed to the top of stack
|
||
r @ ! Write it over the current top of return stack
|
||
r @ 1 + r ! Increment the return stack pointer--but can't use inc
|
||
r @ ! Store our return address back on the return stack
|
||
;</code></pre>
|
||
<p>Next we want the opposite routine, which pops the top
|
||
of the return stack, and puts it on the normal stack.</p>
|
||
<pre><code> : fromr
|
||
r @ @ Save old value
|
||
r @ 1 - r ! Decrement pointer
|
||
r @ @ Get value that we want off
|
||
swap Bring return address to top
|
||
r @ ! Store it and return
|
||
;</code></pre>
|
||
<p>Now, if we have a routine that’s recursing, and we
|
||
want to be polite about the return stack, right before
|
||
we recurse we can run <code>{ fromr drop }</code> so the stack won’t
|
||
blow up. This means, though, that the first time we
|
||
enter this recursive routine, we blow our <em>real</em> return
|
||
address–so when we’re done, we’ll return up two levels.
|
||
To save a little, we make <code>tail</code> mean <code>{ fromr drop }</code>;
|
||
however, it’s more complex since there’s a new value on
|
||
top of the return stack.</p>
|
||
<pre><code> : tail fromr fromr drop tor ;</code></pre>
|
||
<p>Now, we want to do <code>if</code>. To do this, we need to convert
|
||
values to boolean values. The next few words set this
|
||
up.</p>
|
||
<p><code>minus</code> gives us unary negation.</p>
|
||
<pre><code> : minus 0 swap - ;</code></pre>
|
||
<p>If top of stack is boolean, <code>bnot</code> gives us inverse</p>
|
||
<pre><code> : bnot 1 swap - ;</code></pre>
|
||
<p>To compare two numbers, subtract and compare to <code>0</code>.</p>
|
||
<pre><code> : < - <0 ;</code></pre>
|
||
<p><code>logical</code> turns the top of stack into either <code>0</code> or <code>1</code>.</p>
|
||
<pre><code> : logical
|
||
dup Get two copies of it
|
||
0 < 1 if < 0, 0 otherwise
|
||
swap minus Swap number back up, and take negative
|
||
0 < 1 if original was > 0, 0 otherwise
|
||
+ Add them up--has to be 0 or 1!
|
||
;</code></pre>
|
||
<p><code>not</code> returns 1 if top of stack is 0, and 0 otherwise</p>
|
||
<pre><code> : not logical bnot ;</code></pre>
|
||
<p>We can test equality by subtracting and comparing to <code>0</code>.</p>
|
||
<pre><code> : = - not ;</code></pre>
|
||
<p>Just to show how you compute a branch: Suppose you’ve
|
||
compiled a call to branch, and immediately after it is
|
||
an integer constant with the offset of how far to branch.
|
||
To branch, we use the return stack to read the offset, and
|
||
add that on to the top of the return stack, and return.</p>
|
||
<pre><code> : branch
|
||
r @ Address of top of return stack
|
||
@ Our return address
|
||
@ Value from there: the branch offset
|
||
r @ @ Our return address again
|
||
+ The address we want to execute at
|
||
r @ ! Store it back onto the return stack
|
||
;</code></pre>
|
||
<p>For conditional branches, we want to branch by a certain
|
||
amount if true, otherwise we want to skip over the branch
|
||
offset constant–that is, branch by one. Assuming that
|
||
the top of the stack is the branch offset, and the second
|
||
on the stack is <code>1</code> if we should branch, and <code>0</code> if not, the
|
||
following computes the correct branch offset.</p>
|
||
<pre><code> : computebranch 1 - * 1 + ;</code></pre>
|
||
<p>Branch if the value on top of the stack is <code>0</code>.</p>
|
||
<pre><code> : notbranch
|
||
not
|
||
r @ @ @ Get the branch offset
|
||
computebranch Adjust as necessary
|
||
r @ @ + Calculate the new address
|
||
r @ ! Store it
|
||
;</code></pre>
|
||
<p><code>here</code> is a standard FORTH word which returns a pointer to
|
||
the current dictionary address–that is, the value of
|
||
the dictionary pointer.</p>
|
||
<pre><code> : here h @ ;</code></pre>
|
||
<p>We’re ALL SET to compile <code>if...else...then</code> constructs!
|
||
Here’s what we do. When we get <code>if</code>, we compile a call
|
||
to <code>notbranch</code>, and then compile a dummy offset, because
|
||
we don’t know where the <code>then</code> will be. On the <em>stack</em>
|
||
we leave the address where we compiled the dummy offset.
|
||
<code>then</code> will calculate the offset and fill it in for us.</p>
|
||
<pre><code> : if immediate
|
||
' notbranch , Compile notbranch
|
||
here Save the current dictionary address
|
||
0 , Compile a dummy value
|
||
;</code></pre>
|
||
<p><code>then</code> expects the address to <code>fixup</code> to be on the stack.</p>
|
||
<pre><code> : then immediate
|
||
dup Make another copy of the address
|
||
here Find the current location, where to branch to
|
||
swap - Calculate the difference between them
|
||
swap ! Bring the address to the top, and store it.
|
||
;</code></pre>
|
||
<p>Now that we can do <code>if...then</code> statements, we can do
|
||
some parsing! Let’s introduce real FORTH comments.
|
||
<code>find-)</code> will scan the input until it finds a <code>)</code>, and
|
||
exit.</p>
|
||
<pre><code> : find-)
|
||
key Read in a character
|
||
')' = Compare it to close parentheses
|
||
not if If it's not equal
|
||
tail find-) repeat (popping R stack)
|
||
then Otherwise branch here and exit
|
||
;
|
||
|
||
: ( immediate
|
||
find-)
|
||
;
|
||
|
||
( we should be able to do FORTH-style comments now )
|
||
|
||
( now that we've got comments, we can comment the rest of the code
|
||
in a legitimate [self parsing] fashion. Note that you can't
|
||
nest parentheses... )
|
||
|
||
: else immediate
|
||
' branch , ( compile a definite branch )
|
||
here ( push the backpatching address )
|
||
0 , ( compile a dummy offset for branch )
|
||
swap ( bring old backpatch address to top )
|
||
dup here swap - ( calculate the offset from old address )
|
||
swap ! ( put the address on top and store it )
|
||
;
|
||
|
||
: over _x! _y! _y _x _y ;
|
||
|
||
: add
|
||
_x! ( save the pointer in a temp variable )
|
||
_x @ ( get the value pointed to )
|
||
+ ( add the incremement from on top of the stack )
|
||
_x ! ( and save it )
|
||
;
|
||
|
||
: allot h add ;
|
||
|
||
: maybebranch
|
||
logical ( force the TOS to be 0 or 1 )
|
||
r @ @ @ ( load the branch offset )
|
||
computebranch ( calculate the condition offset [either TOS or 1])
|
||
r @ @ + ( add it to the return address )
|
||
r @ ! ( store it to our return address and return )
|
||
;
|
||
|
||
: mod _x! _y! ( get x then y off of stack )
|
||
_y _y _x / _x * ( y - y / x * x )
|
||
-
|
||
;
|
||
|
||
: printnum
|
||
dup
|
||
10 mod '0' +
|
||
swap 10 / dup
|
||
if
|
||
printnum
|
||
echo
|
||
else
|
||
drop
|
||
echo
|
||
then
|
||
;
|
||
|
||
: .
|
||
dup 0 <
|
||
if
|
||
'-' echo minus
|
||
then
|
||
printnum
|
||
'space' echo
|
||
;
|
||
|
||
: debugprint dup . cr ;
|
||
|
||
( the following routine takes a pointer to a string, and prints it,
|
||
except for the trailing quote. returns a pointer to the next word
|
||
after the trailing quote )
|
||
|
||
: _print
|
||
dup 1 +
|
||
swap @
|
||
dup '"' =
|
||
if
|
||
drop exit
|
||
then
|
||
echo
|
||
tail _print
|
||
;
|
||
|
||
: print _print ;
|
||
|
||
( print the next thing from the instruction stream )
|
||
: immprint
|
||
r @ @
|
||
print
|
||
r @ !
|
||
;
|
||
|
||
: find-"
|
||
key dup ,
|
||
'"' =
|
||
if
|
||
exit
|
||
then
|
||
tail find-"
|
||
;
|
||
|
||
: " immediate
|
||
key drop
|
||
' immprint ,
|
||
find-"
|
||
;
|
||
|
||
: do immediate
|
||
' swap , ( compile 'swap' to swap the limit and start )
|
||
' tor , ( compile to push the limit onto the return stack )
|
||
' tor , ( compile to push the start on the return stack )
|
||
here ( save this address so we can branch back to it )
|
||
;
|
||
|
||
: i r @ 1 - @ ;
|
||
: j r @ 3 - @ ;
|
||
|
||
: > swap < ;
|
||
: <= 1 + < ;
|
||
: >= swap <= ;
|
||
|
||
: inci
|
||
r @ 1 - ( get the pointer to i )
|
||
inc ( add one to it )
|
||
r @ 1 - @ ( find the value again )
|
||
r @ 2 - @ ( find the limit value )
|
||
<=
|
||
if
|
||
r @ @ @ r @ @ + r @ ! exit ( branch )
|
||
then
|
||
fromr 1 +
|
||
fromr drop
|
||
fromr drop
|
||
tor
|
||
;
|
||
|
||
: loop immediate ' inci @ here - , ;
|
||
|
||
: loopexit
|
||
|
||
fromr drop ( pop off our return address )
|
||
fromr drop ( pop off i )
|
||
fromr drop ( pop off the limit of i )
|
||
; ( and return to the caller's caller routine )
|
||
|
||
: execute
|
||
8 !
|
||
' exit 9 !
|
||
8 tor
|
||
;
|
||
|
||
: :: ; ( :: is going to be a word that does ':' at runtime )
|
||
|
||
: fix-:: immediate 3 ' :: ! ;
|
||
fix-::
|
||
|
||
( Override old definition of ':' with a new one that invokes ] )
|
||
: : immediate :: ] ;
|
||
|
||
: command
|
||
here 5 ! ( store dict pointer in temp variable )
|
||
_read ( compile a word )
|
||
( if we get control back: )
|
||
here 5 @
|
||
= if
|
||
tail command ( we didn't compile anything )
|
||
then
|
||
here 1 - h ! ( decrement the dictionary pointer )
|
||
here 5 @ ( get the original value )
|
||
= if
|
||
here @ ( get the word that was compiled )
|
||
execute ( and run it )
|
||
else
|
||
here @ ( else it was an integer constant, so push it )
|
||
here 1 - h ! ( and decrement the dictionary pointer again )
|
||
then
|
||
tail command
|
||
;
|
||
|
||
: make-immediate ( make a word just compiled immediate )
|
||
here 1 - ( back up a word in the dictionary )
|
||
dup dup ( save the pointer to here )
|
||
h ! ( store as the current dictionary pointer )
|
||
@ ( get the run-time code pointer )
|
||
swap ( get the dict pointer again )
|
||
1 - ( point to the compile-time code pointer )
|
||
! ( write run-time code pointer on compile-time pointer )
|
||
;
|
||
|
||
: <build immediate
|
||
make-immediate ( make the word compiled so far immediate )
|
||
' :: , ( compile '::', so we read next word )
|
||
2 , ( compile 'pushint' )
|
||
here 0 , ( write out a 0 but save address for does> )
|
||
' , , ( compile a push that address onto dictionary )
|
||
;
|
||
|
||
: does> immediate
|
||
' command , ( jump back into command mode at runtime )
|
||
here swap ! ( backpatch the build> to point to here )
|
||
2 , ( compile run-code primitive so we look like a word )
|
||
' fromr , ( compile fromr, which leaves var address on stack )
|
||
;
|
||
|
||
|
||
: _dump ( dump out the definition of a word, sort of )
|
||
dup " (" . " , "
|
||
dup @ ( save the pointer and get the contents )
|
||
dup ' exit
|
||
= if
|
||
" ;)" cr exit
|
||
then
|
||
. " ), "
|
||
1 +
|
||
tail _dump
|
||
;
|
||
|
||
: dump _dump ;
|
||
|
||
: # . cr ;
|
||
|
||
: var <build , does> ;
|
||
: constant <build , does> @ ;
|
||
: array <build allot does> + ;
|
||
|
||
: [ immediate command ;
|
||
: _welcome " Welcome to THIRD.
|
||
Ok.
|
||
" ;
|
||
|
||
: ; immediate ' exit , command exit
|
||
|
||
[
|
||
|
||
_welcome</code></pre>
|
||
<hr style="width:10%;text-align:left;margin-left:0">
|
||
<p>Jump to: <a href="#">top</a></p>
|
||
<!--
|
||
|
||
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
|
||
|
||
You are free to share and adapt this file under the terms of this license:
|
||
|
||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||
|
||
For more information, see:
|
||
|
||
https://creativecommons.org/licenses/by-sa/4.0/
|
||
|
||
-->
|
||
<!-- AFTER: last line of markdown file: 1992/buzzard.2/buzzard.2.design.md -->
|
||
|
||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||
<!-- START: this line starts content from: inc/footer.default.html -->
|
||
|
||
<!--
|
||
|
||
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
|
||
|
||
You are free to share and adapt this file under the terms of this license:
|
||
|
||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||
|
||
For more information, see:
|
||
|
||
https://creativecommons.org/licenses/by-sa/4.0/
|
||
|
||
-->
|
||
|
||
<div class="footer">
|
||
|
||
<div id="copyright"><h3>Copyright © 1984-2024 by Landon Curt Noll:
|
||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||
<p>
|
||
This work is <b>licensed by Landon Curt Noll</b> under
|
||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||
target="_blank"
|
||
rel="license noopener noreferrer"
|
||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/cc.png"
|
||
alt="cc inside circle symbol">
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/by.png"
|
||
alt="person inside circle symbol">
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/sa.png"
|
||
alt="arrow looping back on itself inside circle symbol"><br>
|
||
You should <b>carefully review</b> the
|
||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||
before using the licensed material.<br>
|
||
You may wish to review the
|
||
<b><a href="../../license.html"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||
of <b>CC BY-SA 4.0</b>.<br>
|
||
</p>
|
||
</div>
|
||
|
||
<div id="coda"><h3>Coda</h3>
|
||
<p>
|
||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fwww.ioccc.org%2F1992%2Fbuzzard.2%2Fbuzzard.2.design.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a>
|
||
</p>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/footer.default.html -->
|
||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||
|
||
</body>
|
||
</html>
|
||
|
||
<!-- END: this line ends content from: inc/bottom.default.html -->
|