teodoran / stck

stck is a stack-based programming language
25 stars 4 forks source link
esoteric-language fsharp programming-language stack-based stck

STCK

a stack-based programming language

STCK logo

Build status codecov

Try STCK in the browser

"INTERCAL allows only 2 different types of variables, the 16-bit integer and the 32-bit integer." - From the INTERCAL Programming Language Revised Reference Manual

STCK (pronounced stick) is is a programming language inspired by Forth. Variables are never declared, values is just placed on a global stack. Syntax is minimal.

The only supported data-type used to be 32-bit integers, but now we handle all that with Church encoding.

Installation

You'll need the .NET 7.0 SDK to compile the STCK interpreter.

When the compiler is installed, navigate to the folder /Stck.Console and run:

dotnet restore
dotnet build
dotnet run

This should compile and launch the interactive interpreter. Execute quit to get out.

Using the language

"Beware of the Turing tar-pit in which everything is possible but nothing of interest is easy." - Alan J. Perlis

Pushing symbols

Write a word, any word, and press enter. You now have a symbol on the stack.

$> any-word
[any-word]

Write another one, and then another.

$> another-one and-then-another
[any-word another-one and-then-another]

You now got three symbols on the stack. What can I do with those you might ask, and that would be a nice segway into...

Working with the stack

_"A goal of a good Forth programmer is to minimize the use of these words, since they are only moving data around instead of doing useful work." - From the The OLPC Wiki_

. will drop one element from the stack.

[any-word another-one and-then-another]
$> .
[any-word another-one]

swap will swap the two upmost elements on the stack.

[any-word another-one]
$> swap
[another-one any-word]

dup will duplicate the topmost element on the stack (TOS)

[another-one any-word]
$> dup
[another-one any-word any-word]

2dup will duplicate the two topmost elements on the stack.

[another-one any-word any-word]
$> 2dup
[another-one any-word any-word any-word any-word]

Did I mention that you can drop several elements at once?

[another-one any-word any-word any-word any-word]
$> ...
[another-one any-word]

over will copy the second element on the stack.

[another-one any-word]
$> over
[another-one any-word another-one]

rot will move the third element to the top of the stack.

[another-one any-word another-one]
$> rot
[any-word another-one another-one]

empty will check if the stack is empty, and push the result onto the stack as a Church encoded boolean.

[any-word another-one another-one]
$> empty
[any-word another-one another-one [. swap]]
$> clear
[]
$> empty
[[.]]

In addition, the Forth documentation has a good description of different stack operators, along with reference implementations for less basic operators.

Math

_"For every epsilon>0 there is a delta>0 such that whenever |x-x_0|<delta, then |f(x)-f(x0)|<epsilon." - From [Wikipedia](https://en.wikipedia.org/wiki/(%CE%B5,%CE%B4)-definition_oflimit)

All numerals are Church encoded and the following operators are supported: + (addition), - (subtraction), * and % (modulo). All operators perform on the two upmost elements on the stack, and push the result back on the stack as one number.

[]
$> 1 1 +
[2]

Numerals and booleans are "unchurched" for readability. This can be turned off with the command church.

[2]
$> church
[[app || << rot rot << swap rot dup rot [app [app || swap rot dup swap [.]]] [app [app || swap rot dup swap [.]]]]]

You can turn on unchurching again with the command unchurch. Reading stdlib.md might help if that didn't make a lot of sense.

In addition the following predicates are supported for comparing numbers: is-zero, <= (less or equal), >= (greater or equal) and = (equal).

Booleans

Booleans are also Church encoded, and again stdlib.md is your friend. true is true and falseis false.

The following boolean operators are supported: not (not), and (and), or (or), xor (xor), <- (left implication), -> (right implication) and <-> (equivalence).

Anonymous stacks (Quotations)

"Anonymous stacks gives STCK the power of lambda functions™" - Anonymous STCK developer

Chunks of STCK code can be pushed to the stack inside of anonymous stacks.

[]
$> [false not]
[[false not]]

Note how false and not wasn't executed. At a later time, the contents of an anonymous stack can be applied to the stack using app.

[[false not]]
$> app
[true]

Anonymous stacks can be nested.

$> [this [is [nested]]]
[[this [is [nested]]]]
$> app
[this [is [nested]]]
$> app
[this is [nested]]
$> app
[this is nested]

A different set of stack operators work on anonymous stacks.

|| (concat) will concatenate two anonymous stacks.

$> [a b] [c d] ||
[[a b c d]]

| (chop) will chop off the first element of the anonymous stack into a new anonymous stack.

$> [a b c] |
[[a] [b c]]

<< (ontop) pushes an element to the front of another anonymous stack.

$> [last] first <<
[[first last]]

>> (ontail) pushes an element to the end of another anonymous stack.

$> [last] first >>
[[last first]]

Conditionals

Conditionals follow the good old then-else-if construct: <a boolean> [this anonymous stack will be applied if true] [this anonymous stack will be applied if false] ?

[]
$> true [this anonymous stack will be applied if true] [this anonymous stack will be applied if false] ?
[this anonymous stack will be applied if [.]]

[]
$> false [hot] [or-not] ?
[or-not]

To be precise ? is a subroutine that pops three elements from the stack, considers the last one to be a boolean, and applies either one or the other of the arguments.

Subroutines

"What is a definition? Well classically a definition was colon something, and words, and end of definition somewhere." - Chuck Moore

Subroutines are declared by using #:

[5 +] add-five #
$> 2 add-five
[7]

Comments

"Due to INTERCAL's implementation of comment lines, most error messages are produced during execution instead of during compilation." - From the INTERCAL Programming Language Revised Reference Manual

``` indicates the start and end of a comment. This is useful, as it enables STCK-programs to be embedded in markdown files.

[]
$> ```This is a comment!```
[]

Utility functions

The interpreter defines a couple of utility functions, not strictly part of the STCK language.

hprint prints the content of the heap. This will list all declared subroutines.

quit exits the interpreter.

load loads external STCK-programs.

Projects using STCK

hyperstck - A hypermedia-driven evaluator for the Stck programming language

REST-STCK - Arbitrary Computation as a Service (ACaaS)