#lang scribble/doc

@(require 
   scheme/sandbox
   scheme/enter
   scribble/manual
   scribble/eval)

@(define scat-eval (make-base-eval))
@(define-syntax ex
   (syntax-rules ()
     ((_ () . args)
      (interaction #:eval scat-eval . args))
     ((_ . args)
      (defs+int #:eval scat-eval . args))))

       



@title{Staapl}

@section{Introduction}

Staapl is a collection of abstractions for (meta)programming
microcontrollers from within @link["http://www.plt-scheme.org"]{PLT
Scheme}. The core of the system is a programmable code generator
structured around a functional
@link["http://en.wikipedia.org/wiki/Concatenative_programming_language"]{
concatenative} macro language called Coma with a pattern matching
language for defining primitive code transformers in Scheme. On top of
this it includes a syntax frontend for creating
@link["http://en.wikipedia.org/wiki/Forth_%28programming_language%29"]{Forth}
style languages, a backend code generator for the Microchip PIC18
microcontroller architecture, and interaction tools for shortening the
edit-compile-run cycle.

The primary, practical goal is to provide a tool chain for programming
8-bit microcontrollers in a Forth-style language extended with
powerful metaprogramming facilities. The secondary goal is to
generalize and modularize this approach, and distill a collection of
domain specific languages (DSLs).

In contrast to most current research in RAP, Staapl uses predominantly
dynamic typing with some static analysis built on top, and avoids
variable binding problems by using point-free target languages. The
reason for this is a pragmatic one. While static typing provides more
guarantees about the properties of programs, it is also not
insignificantly more difficult to evolve such a system according to
practical needs, when requirements aren't completely clear at the
onset. Moreover, macros are easier to understand in a dynamic
language, which makes the entry level simpler. I found it easier to
grow static structure on top of a dynamic language, an approach which
is predominant in the PLT Scheme programming system on which Staapl is
based.

Staapl is currently split into two main parts: a language part
comprising the purely functional concatenative (compositional) Scat
and Coma languages, and a couple of libraries and language extensions
that solve practical problems such as Forth-specific syntax and
semantics, control flow analysis, optimization sequencing, and live
target interaction.


@section{Metaprogramming}

When you are no longer able to directly express some high level
specification of a solution in the language you are working with,
you've reached the @emph{abstraction ceiling}. Working with embedded
systems in C or assembly language, quite often the need arises to
@emph{manually compile} an implementation derived from a higher level
solution description. For one-time specific implementations, this is
not problematic.

Struck by sudden flash of genius, people that run into this problem
often enough to get annoyed with it start writing small scripts in some
high level language to generate the desired low-level code
fragment. This pattern of splitting up the construction of a low-level
description from a chain of higher level ones is usually called
@emph{staging}. Big companies spend a lot of resources to build or buy
elaborate generator tools, and there is quite some research literature
about how to tackle this problem in somewhat optimal ways for specific
domains. Especially interesting in this respect is MetaOcaml, which
combines staged programming with the guarantees of a type system.

So, all in all, nothing new under the sun. Then, what's the place of
Staapl? The itch that it scratches is the lack of integrated and
practically oriented open source tools that provide a convenient
approach to metaprogramming. The main ideas are: when building a code
generator, you will need the flexibility of a powerful all-purpose
programming language at some time, but you also want to keep a firm
grip on the low-level side. Within these constraints, please maximize
convenience.

Staged programming can provide extra composition mechanisms to extend
a language's limited composition mechanisms. The essential realization
in Staapl is that when resource constraints @emph{force} you to use a
base language with a fairly low abstraction ceiling, you are going to
resort to metaprogramming of some sort somewhere down the line. When
this inevitability is there, you had better thought about how to make
this metaprogramming as straightforward as possible.  Instead of
connecting the base language compiler and the meta code generator
through text files with an ad-hoc language syntax that requires
printers and parsers, it might be a better idea to somehow connect the
programs @emph{directly} by using well-defined data structures in an
integrated framework. In Staapl, this framework is to use a Lisp-like
language to generate code for a Forth-like language, more specifically
PLT Scheme which has a lot of supporting code to create such a system,
and a cleaned-up, pure, non-reflective version of Forth, which has a
simple code structure that avoids one of the most awkward problems in
metaprogramming: handling variable bindings correctly.


To summarize:

@itemize{

  @item{Accept that when you are writing resource constrained
    programs, you are going to run into an abstraction ceiling.}

  @item{Move complexity and abstraction to the meta level by writing
    template code.}

  @item{Write code generators in a high level language in order to
    avoid further abstraction ceilings.}

  @item{Use a base language that is specifically designed to play nice
    with the metaprogramming system.}

}

The Staapl system is structured as a library of components that will
be described in the following sections. Some examples illustrate how
to glue these components together to provide two common workflows:
batch compilation from source to binary, and console interaction.  You
are encouraged to open op this top level glue and adapt it to your
own preferred workflow.

@section{Scat}

This section introduces Scat, a set of special forms for PLT Scheme
implementing a concatenative (compositional) language usable inside
scheme code. Scat is part of the Staapl code base, where it serves as
an intermediate language layer for a Forth compiler (through Coma) and
live interaction and simulation system. Scat is a minor modification
of the Joy language to make it less reflective and more similar to
Scheme.

@ex[
  ()
  (require (planet zwizwa/staapl/scat))
]

Scat's composition mechanism is made available through a single macro
@scheme[scat:], which interprets its arguments as Scat functions and
produces a composite Scat function. Scat functions are unary endomaps
of (a subclass of) the @scheme[state] type. Most Scat functions
operate on the @scheme[stack] subclass, which contains a stack of values,
implemented as a list.

@ex[ ()
     (stack-list
      ((scat: 100 +)
       (make-state:stack '(1 2 3))))
]

Here @scheme[100] names a function that pushes the number @scheme[100]
on the stack and @scheme[+] names a function that combines the two top
elements into a single number. @scheme[make-state:stack] creates a
@scheme[stack] object from a list, and @scheme[stack-list] accesses
the stack slot in a state object.

To create (primitive) Scat functions in terms of Scheme code, the form
@scheme[stack-lambda] can be used, which will destructure the stack
list in a (subclass of the) @scheme[stack] type.

@ex[()
  (stack-list
   ((stack-lambda (a . s)
     (list* a a s))
    (make-state:stack '(123 a b c))))
]

Scat functions live in a separate namespace.  This is implemented by
prefixing identifier names, so Scat functions can coexist with Scheme
functions in the same concrete Scheme namespace.  To add entries to a
Scat namespace, use @scheme[define-ns]. These can again be referenced
with @scheme[ns].

@ex[((define-ns (scat) foo (scat: 1 2 3)))
    (stack-list
     ((ns (scat) foo) (make-state:stack '())))
]


The rest of the documentation will abstract the use of the
@scheme[stack] datatype used for threading state through function
compositions, which enables us to focus on functions only. The macro
@scheme[scat>] serves as the REPL for Scat code. It passes its
arguments to @scheme[scat:], applies the resulting function to the
empty stack, and prints the stack value of the result. In the printed
output, the number between brackets is the size of the stack. The
rightmost value is the top.

@ex[ ()
        (scat> 1 2 3)
]


Identifiers occurring in a @scheme[scat:] form are always referenced
using the @scheme[ns] macro applied to the @scheme[(scat)] namespace.
A lot of these functions are derived from the standard Scheme function
with the same name. Data that are not identifiers are self-quoting: a
datum refers to a function that places the corresponding datum on the
top of the stack.

To facilitate metaprogramming of Scat from Scheme code, identifiers in
the lexical Scheme environment can be referenced using
@scheme[unquote].  Their values either represent Scat functions when
they occur unquoted in Scat code, or literals when they occur quoted,
similar to Scheme's @scheme[quasiquote].

@ex[()
             (let
                 ([one 1]
                  [inc (scat: 1 +)])
               (scat> ',one ,inc))
]


Lists in Scat code bodies are interpreted as anonymous code
compositions, also called quoted programs, which are not executed but
left on the stack in quoted form instead. These quoted programs are
ordinary Scat functions, and can be used by higher order functions
like @scheme[run] to instantiate delayed behaviour.

@ex[()
           (scat> 100 (1 +) run)

]

Conditional execution is implemented by the higher order function
@scheme[ifte]

@ex[
             ((define-ns (scat) foo 
                 (scat: (1 +) (1 -) ifte)))
             (scat> 100 #t foo)
             (scat> 100 #f foo)
]

Contrary to Joy, where quoted programs are also lists, quoted programs
in Scat are abstract entities and cannot be deconstructed. This trades
some reflection abilities for a more general program type: one that
does not need to have a textual representation.
@ex[() (scat> '(1 2 3)) (scat> (1 2 3)) ]


On the implementation side, some macros are provided to ease the
creation of Scat code from Scheme code using the @scheme[snarf]
macro. Snarfing boils down to declaring the number of input and output
arguments of Scheme functions.  For an example, see the file
@scheme[scat/scat-base.ss]. The Scat semantics and syntax are
extensible through the use of a set of compile-time parameters. See
the file @scheme[scat/rpn-tx.ss] for more information. This extension
mechanism is used in Staapl to define the Coma language, a purely
functional concatenative language with threaded compilation state used
to represent Forth macros, and the Tscat language for assembly time
expression evaluation. The exact mechanism of these low-level
constructs might change, so the interface is not documented as of yet.

Constructing Scat programs is done using the Scheme special form
@scheme[compositions]. As an example, here's an excerpt from the
standard library:

@ex[()
 (compositions
   (scat)    scat:

   (swons    swap cons)
   (unswons  uncons swap))
]

The first argument to @scheme[compositions] is the name space in which
to define new identifiers. The second argument is the form to be used
to construct programs to bind to the names. The following forms
contain lists where the first element is an identifier taken as the
name of a function, and the remaining elements are taken as the
composition body. The printed output indicates that these names have
been redefined. The form expands to

@ex[()
    (begin
      (define-ns (scat) swons   (scat: swap cons))
      (define-ns (scat) unswons (scat: uncons swap)))
]


@section{Coma}


Staapl contains a language for concatenative macros (Coma) implemented
on top of Scat. This is a purely functional extension consisting of a
set of functions that operate on stacks of (virtual) machine
instructions.  There are essentially no restrictions for the form of
this machine language, but Coma is most useful for representing stack
machine instructions, where programs are built from a concatenation of
primitive instructions that operate on a parameter stack.

@ex[
  ()
  (require (planet zwizwa/staapl/coma))
]

The virtual machine used in the core Coma implementation uses 5
instructions: @scheme[qw] to quote a data item and load it on the
stack, @scheme[cw] to invoke a subroutine and return to the next
function following the invocation, @scheme[exit] to abort the
execution of the current procedure, @scheme[jw] to perform a tail call
and @scheme[jw/if] to perform a conditional tail call.

The power of Coma can be understood by the following observation:
applying Scat's @scheme[dup] function to a stack containing a single
@scheme[qw] instruction produces a stack with two @scheme[qw]
instructions. The semantics of @scheme[dup] in Scat essentially
transfers to the generated machine language program. A program that
quotes a single number is transformed into a program that quotes the
same number twice, with the duplication operation moved to program
generation time. This is called staging: the transformation of a
program into a program generator.  The function @scheme[dup] is a
program that transforms an input program into an output program. More
generally, if the input program is empty, the program transformer is a
program generator, which is also called a macro.

In order to properly separate Scat words from words that operate on
machine code exclusively, a new namespace called @scheme[(macro)] is
introduced. Together with this namespace come Scheme forms to perform
function composition and to provide REPL functionality, respectively
@scheme[macro:] and @scheme[macro>]. The latter form prints machine
code program that is the result of instantiating the provided macro
composition. These operate in a way similar to @scheme[scat:] and
@scheme[scat>], but taking identifiers from a different name
space. Note that a literal value has a different semantics: it
evaluates to a program quoting the literal.

@ex[
  ()
  (macro> 1 2 3)
  (macro> 1 2 +)
]

Note that the function @scheme[+] performs partial evaluation: instead
of inserting machine code to perform the operation, the computation is
performed at compile time and a program quoting only the result of
that computation is produced. This is called partial evaluation.

@section{Primitives}

Staapl includes a specification language provided as a Scheme form
@scheme[patterns] for declaring primitive code transformers based on a
pattern matching syntax, and an evaluation language represented by the
@scheme[tscat:] special form to construct compile time computations,
possibly parameterized by code addresses. For example, the code
implementing the @scheme[-] macro is declared as:

@ex[
 ()
 (patterns (macro) 
   (([qw a] [qw b] -)        ([qw (tscat: a b -)]))
   (([addlw a] [qw b] -)     ([addlw (tscat: a b -)]))
   (([qw a] -)               ([addlw (tscat: a -1 *)]))   
   (([save] [movf a 0 0] -)  ([bpf 0 STATUS 0 0] [subfwb a 0 0])) 
   ((-)                      ([subwf POSTDEC0 0 0])))
]

The form @scheme[patterns] constructs a polymorphic macro @scheme[-]
which produces different output programs depending on 5 types of input
program patterns. The form @scheme[tscat:] is a concatenative
evaluation language which extends the basic Scat semantics by
interpreting lexical Scheme names as quoted constants. For example the
input pattern @scheme[([qw 1] [qw 2] -)] will be matched by the first
rewrite rule, binding the Scheme identifiers @scheme[a] and @scheme[b]
to the values @scheme[1] and @scheme[2] respectively. These names are
then visible within the @scheme[tscat:] code composition and
interpreted as parameterized constants, while the identifier
@scheme[-] is not lexically visible and therefore taken from the
@scheme[(scat)] Scat namespace.


@section{Forth}

To represent Forth-style control words like @scheme[begin] and
@scheme[again], the Scat state needs to be extended with an extra
control stack that holds machine code labels which serve as branch
targets. In classic Forth, this functionality is implemented as
immediate words that execute at compile time with access to a control
stack to construct nested structured programming constructs.

@ex[
  ()
  (require (planet zwizwa/staapl/control))
]


Unrestricted branching introduces the possibility to create graph
structures which means machine code is not longer
concatenative. However, the macro language that generates these
structures is still a purely functional concatenative language. As a
result, these control structures can still be composed.

@ex[
  ()
  (macro> begin 123 again)
]

Historically, the Forth dialect called Purrr is the seed from which
Staapl grew, but it is now considered to be an evolutionary dead end,
which means the Purrr language can be considered stable.

Forth (Coma with explicit control stack) is a very useful language for
writing lowlevel code, precisely because of the ability to write
abstractions around low level branching operations. However, this
structure also makes it harder to analyse statically. While the Forth
compiler in Staapl performs some static control-flow analysis and
there is room for more, the Forth layer serves mainly as a somewhat
standard programmer interface for writing low-level code at places
where the kind of manual control provided is necessary.

Most attention in the future will be directed at the conceptually
cleaner Coma language core which is more suited for static analysis in
the form of type systems or program transformation
algebras. Fortunately, Coma can be trivially embedded within the Purrr
Forth dialect, precisely because Purrr is a clean factorization as
Coma + Control.

The control stack is not the only extension necessary to implement a
somewhat standard Forth language on top of Coma. Staapl contains a
Forth-style lexer and a preprocessor to finish the job. The latter is
the analog of Forth's parsing words: it allows the composition of
Forth constructs that act as prefix tags to change the meaning of
following words. For example the Forth word @scheme[:] starts a new
definition, changing the the meaning of the following source text word
which is taken as the name of the to-be-defined function.

In Purrr, this preprocessing mechanism has been kept extensible to not
run into an abstraction wall, but is essentially ad-hoc following the
ad-hoc reflection in the classic Forth language. The lexer in Purrr is
not extensible in the same manner.

Note that Purrr differs from traditional Forth in that it is
cross-compiled and not self-reflective but constructed as an acyclic
language tower. This leads to essentially 3 different composition
mechanisms: a primitive rewrite language @scheme[patterns], a purely
concatenative Coma @scheme[compositions] and a preprocessing rewrite
language represented by the form @scheme[substitutions]. The first two
are essential non-reducible components (primitive code transformers +
composition of transformers) of Coma, while the latter is a
consequence of the particularities of Forth syntax. With an extensible
lexer, it would be 4. It is my opinion that the benefits of an
unrolled reflection tower more than compensate the extra complexity in
1 (or 2) preprocessing steps necessary to construct a Forth style
language around a clean functional language core. The scheme
@scheme[substitutions] form is also used to define a Forth style
interaction language, next to these compile time constructs.



@section{Specialization}

By adding target specific transformation rules, this mechanism can be
used to generate machine code for a concrete machine. Staapl includes
a specialization for the Microchip PIC18 architecture.

@ex[
  ()
  (require (planet zwizwa/staapl/pic18))
]

This allows for example partial evaluation to partially applied binary
functions:

@ex[
  ()
  (macro> 1 +)
]

Here the transformer @scheme[1 +] generates a program that adds
the literal number @scheme[1] to the working register, which contains
the top of the run-time parameter stack.


@section{Parameterization}

Two observations are important. First, the pattern matching language
@scheme[pattern] for defining primitive code transformers allows the
definition local operations on a stack of tagged values.  Machine
instructions are represented as Scheme lists, with the first value is
a symbol indicating its type, and the @scheme[pattern] form provides
syntactic sugar for deconstructing and constructing stacks of tagged
lists.

Second, beyond this first level of matching, the pattern matching
language is PLT Scheme's @scheme[scheme/match]. This means the
@scheme[pattern] language allows the definition of primitive
generators that operate on arbitrary data structures, as long as they
are embedded in a stack of tagged lists. This provides a completely
general, dynamically typed two-stage programming language: machine
code acts as threaded state values passed from one transformer's
evaluation to the next.

@ex[()
    (define-struct foo (a b c))
    (patterns (macro)
     ((foo)                           ([qw (make-foo 1 2 3)]))
     (([qw (struct foo (a b c))] bar) ([qw a] [qw b] [qw c])))
]

Here the generator @scheme[foo] loads a structure on the stack. This
structure is embedded in a @scheme[qw] pseudo-instruction, which
allows it to be manipulated as a (compile time) literal value by
operations like @scheme[dup]. The processor @scheme[bar] consumes the
struct and unwraps it into 3 literal values.

The Scat function composition mechanism allows to glue such code
transformers together. This allows for powerful two-stage programming:
generation can be factored into small special-purpose primitives
defined in Scheme, that can be then combined in Coma/Forth source code
using the usual code concatenation operation.

@section{Concatenative Hygiene}

What is special about this form of two-stage programming is that it
avoids the usual hygiene problems that pop up in code generation. In
transformer primitives, all variable binding follows Scheme's lexical
scoping, while in the concatenative composition combinator language
there is simply no scope to mess up, because the concrete target stack
machine has no scoping mechanism.

To some, the disadvantage might be that a program needs to be written
in a concatenative language. Whether this is good or bad is ultimately
a matter of taste. My opinion is that as a low-level language to
replace assembly code, Forth is really as good as it gets.  It has an
efficient, almost trivial mapping to concrete machine architectures.
It forces a certain programming style, but this style usually leads to
fairly optimal code concerning resource usage. Forth is on the
boundary of imperative and functional programming (point-free style)
which makes it an ideal vehicle for formal structures, i.e. the
functional core of Forth should be easy to integrate with linear
types, which is a promising resource aware programming paradigm
present in a language like LFPL.

The simplified semantics that emerges from the pattern transformer +
concatenative macro approach is fairly straightforward. Source code
has essentially no inline staging annotations: all annotation is
present at the transformer definition site. As a result, staging
semantics can be easily ignored to grasp the meaning of code. After
non-staged semantics is clear, staging annotations can be studied to
see which parts are actually evaluated at compile time. All this is a
consequence of associativity of function composition: by (partly)
modeling the language as a lazy functional one, evaluation time
becomes unimportant for understanding part of the meaning.


@section{Live Session}

Staapl contains code to provide an interactive console modeled after
Forth's interaction model. While Staapl's Forth is not reflective,
it is possible to invoke the compiler on the host and have it upload
code to a running flash-based microcontroller, without disturbing its
running state.

This kind of reflection is organized inside a PLT Scheme namespace
object. A specialized compiler (in this case for PIC18) and its
associated assembler is instantiated inside a namespace separate from
mzscheme's toplevel namespace, and can accept code by loading and
compiling it. Alternatively, code can be imported using PLT Scheme's
@scheme[require] form, in which case the language used is arbitrary
and hidden. These two models: interactive compilation and evaluation
and abstract tree-structured modules are two essential pilars of PLT
Scheme software development translated to the Staapl system.

In order to get this going, let's go through the process of compiling
and uploading some monitor code. First, we load the PIC18 specialized
environment.

@ex[()
    (require (planet zwizwa/staapl/prj/pic18))
]

Inside this environment, which has the PIC18 Forth dialect defined, we
load the source code of the serial interpreter by evaluating some
Forth code.

@ex[()
    (forth-load/compile "monitor-p18f1220.f")
]

Note that if you look inside the
@scheme[staapl/pic18/monitor-p18f1220.fm] file, a small wrapper around
the file we just loaded, you can see it starts with a @litchar{#lang
planet zwizwa/staapl/pic18} line which means it can also be imported
directly into a Scheme namespace as a module using @scheme[require].

To finalize, we save the monitor binary code as an Intel HEX file, and
save the dictionary of target word to address mappings.

@ex[()
    (save-ihex "/tmp/monitor.ihex")
    (save-dict "/tmp/monitor.ss")
]

After uploading this file using a PIC programmer, the PIC18F1220 can
interact with Staapl using a serial 9600 Baud interface. The
dictionary file can be loaded later to inform the Forth system about
the words already present on the target system. The contents of the
file look like:

@ex[()
    (prj-eval '(write-dict))
]

The form @scheme[prj-eval] is used to evaluate arbitrary code within
the current compiler namespace, which is stored in the
@scheme[current-prj] parameter. Most important commands are delegated
from the namespace in which the @scheme[staapl/prj/pic18] module is
imported. Of course, these commands can be saved into a script to be
loaded by the @scheme[mzscheme] interpreter for batch compilation.

Finally, to interact with a live target that is equipped with the
minimal monitor/interpreter, two special forms are provided. The form
@scheme[live-scat>] is @scheme[scat>] with an open connection to the
target's interpreter over a serial port. Target interaction
functionality is defined in @scheme[staapl/live/tethered], and is
useful for directly driving a target from Scheme or Scat code,
i.e. for a test suite.

On top of this direct host->target control functionality there is an
interaction language which emulates a console running on the target
platform. This language is provided through the form
@scheme[target>]. Literal numbers in this language are transferred to
the target's data stack. Identifiers in this language refer either to
target words, in which case the corresponding word is executed on the
target, or to substitution macro words that expand to Scat target
interaction code. This class of commands is defined in
@scheme[staapl/live/commands] using the @scheme[substitutions]
macro. It presents a simplified target-local interface to the
essentially distributed target/host system.

For example, the form @scheme[primitive-subsitutions] will define
prefix words in the @scheme[target>] language in terms of Scat code.

@ex[()
    (primitive-substitutions
     (target) scat:

     ((start w) ('w tfind tstart/w)))
]

This defines the word @scheme[start] which takes the word following it
to be interpreted as the name of a target procedure, of which the word
address is resolved. The target interpreter is then instructed to
execute this word asynchronously, as opposed to useing the synchronous
@scheme[texec/w]. Of course, this mechanism is extensible, so it is
possible to write project-specific interaction commands.

The compiler and interaction system can be addressed in Forth syntax
using the macros @scheme[forth-compile] and
@scheme[forth-command]. The following code is an interaction mode
REPL. See also the scripts in the @scheme[examples/] directory.

@ex[()
(define (repl)
  (let loop ()
    (printf "OK\n")
    (forth-command (read-line))
    (loop)))
]

To interact with Staapl, I use my Snot system, which is a wrapper
around the @scheme[scheme/sandbox] library that provides Emacs
interaction with multiple language prompts. The project contains an
example configuration file @scheme[.snot].

@section{Acknowledgements}

Staapl is the result of a long history of accumulating ideas and
reworking implementations starting with me moving out of my C shoes by
discovering Chuck Moore's colorForth in the fall of 2001, and Scheme
and Joy a bit after that. This has lead to the development of Packet
Forth (2002), Mole (2004), Badnop(2005) and Brood/Staapl(2006). Staapl
is a re-implementation of Badnop. Badnop is a peephole optimizing
Forth cross-compiler written in a Forth dialect, Mole is an embedded
Forth for the graphical programming system Pure Data and Packet Forth
is a Lisp/Forth hybrid that explores multimethods and linear memory
management. The history of these projects is available in the
@link["http://zwizwa.be/darcs"]{archives}. I've made a lot of mistakes
and changes over the years, and I've read a lot about the approaches
and mistakes of others.  While all of the implementation work has been
done by me, the ideas of course come from many places.

Scat was called Cat for a while, until I discovered Christopher
Diggins' efforts. Cat is a typed Joy with a preprocessing term rewrite
system. Cat has fueled my interest in type systems and statically
typed functional languages, which eventually lead to the discovery of
MetaOcaml and Walid Taha's efforts in the RAP domain.  I want to
acknowledge Slava Pestov for being a source of ideas by being verbal
about Factor and his opinions on language design and
implementation. The Forth compiler in Staapl, which evolved from
Badnop, contains ideas from Samuel Tardieu's PicForth and Chuck
Moore's colorForth. An invaluable event was the port of Staapl to PLT
Scheme with its excellent support for writing DSLs. The PLT team has
put together a superb collection of documentation which was
instrumental to my education and growth of the Staapl project. The
ideas behind Packet Forth are inspired by CLOS and Henry Baker's ideas
on linear lisp. Last but not least, I'd like to acknowledge Manfred
von Thun, who's Joy language seems to have been the necessary nudge
that brought Forth into the modern age judging by the number of
Joy-inspired projects out there.


