aboutsummaryrefslogtreecommitdiff
path: root/README.org
blob: 378254066d757455cb10cd39fa472205a31836e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#+title: Stem

* Introduction
Stem aims to be a small implementation of something like the forth programming language,
meaning it operates on a virtual stack. There are words, quotes, and literal types in this
language; this allows for metaprogramming.

** Quickstart
In this language, words are anything that are not literals (strings, ints, floats), and are
not the special characters [ and ]. Literals include the types above and they work just
like in other languages, and quotes are just lists of these words and literals.

Any literal in the language by itself gets pushed onto the stack. For example, the value:
#+begin_example
"hello world"
#+end_example
gets pushed onto the stack once it is created.

Note that words can also act like literals, but they are different in that you can bind them to funtions:
#+begin_example
helloworld [ "hello world" . ] func
#+end_example
Where . is a builtin function that pops the first value off the stack and prints it. In this example, the helloworld
word is pushed onto the stack, then the quote ~[ "hello world" . ]~, which is just an array of these two values. Then,
the ~func~ builtin is called, which takes these two values off of the stack. As a result, whenever ~helloworld~ is used
in the future, it is expanded into whatever is in the quote.

a useful way to know what's on the stack:
#+begin_example
?
#+end_example
is a builtin function that prints everything on the stack, where the very last thing printed is the top of the stack.

*** Quoting and Escaping
If you want to push a word to the stack after it has been bound, you must escape it:
#+begin_example
\helloworld
#+end_example

quotes are somewhat related to escaping. They allow the language to talk about itself, along with the ~eval~ keyword.
To get an idea of what you can do with it, consider the following example:
#+begin_example
[ hello [ "hello" . ] func ] eval
#+end_example
this statement is essentially the same statement as the above, but you can represent the entire code in a quote
before evaluation. This allows for many possibilities. For example, you may try writing a program that automatically
names functions and automatically changes what those functions do.

*** Loops
Looping in this language is done via recursion. Because the language is stack-based, recursion is not more memory efficient
than looping if using tail recursion. For example, the REPL for this language is implemented like so:
#+begin_example
loop [ "> " read evalstr loop ] func loop
#+end_example
Where read takes in a string and prints it before reading a value, evalstr evaluates a string, and loop is the function that calls
itself.

*** Curry, Compose, Qstack, Quote
These functions are important for manipulating quotes. For example:
#+begin_example
[ a b ] 6 5 quote curry compose
#+end_example
first turns 5 into ~[ 5 ]~, then curry adds 6 to the end of the quote. Compose takes two quotes and adjoins them together. Qstack
simply turns everything on the stack into a quote, then puts it on the stack. For example:
#+begin_example
1 2 3 4 5 6 7 qstack
#+end_example
Returns the quote ~[ 1 2 3 4 5 6 7 ]~.