Welcome to TASEL!

TASEL (pronounced TASS-Uhl, like tassel) stands for Totally Awesome Stack Execution Language. It’s a stack-based programming language. Stack-based languages are a type of programming language that operate on a data structure called a stack. In simple terms, a stack is like a pile of objects where you can only interact with the object on the top.

In stack-based languages, you work directly with the stack. You push values onto the stack and perform operations that consume values from the stack and produce new values. The stack follows a “last in, first out” (LIFO) principle, meaning the last value you push onto the stack is the first one you can access or use.

To perform computations, you push the input values onto the stack, then use operators or functions that take values from the stack, perform operations, and push the result back onto the stack.

The beauty of stack-based languages lies in their simplicity and conciseness. They tend to have a compact syntax since they don’t require complex control structures, and often skip the parsing process completely. However, they do require a different mindset and understanding of how the stack operates. By leveraging the stack’s properties effectively, you can create powerful and efficient programs.

Note

TASEL is currently in Beta phase and under development, but it’s available on Replit.

Contents

Documentation

TASEL is small enough that the docs fit on one page!


Note: When there’s text inside of angle brackets (<like this>) inside of a code snippet, (Eg, -> <var name>) it means “replace this with what the text is” (Eg, -> <var name> = -> varNameGoesHere)


When you type a word that is a string (“anything here” or ‘anything here’) or an integer or a float (decimal) it pushes it on to the stack. If it’s a variable, it pushes the value of the variable on to the stack.

Comments

Comments start with # (hash) Eg. # Hello, world!

Variables

-> <var name>

-> assigns the top of the stack to the given variable.

inc:<var name>

Increments the given variable by one.

dec:<var name>

Decrements the given variable by one.

Stack operations

dup

dup duplicates the top item of the stack.

(n1 – n1 n1)

drop

drop drops (removes) the top item of the stack

(n1 n2 – n1)

swap

swap swaps the first two items on the stack

(n1 n2 – n2 n1)

over

over takes the second element from the top of the stack and duplicates it to the top of the stack

(n1 n2 n3 – n1 n2 n3 n2)

rot

rot rotates the top three elements of the stack. The third element from the top of the stack gets moved to the top of the stack, pushing the other two elements down.

(n1 n2 n3 – n3 n1 n2)

cs

cs clears the contents of the stack.

(n1 n2 n3 – )

Arithmatic

+

Adds (or combines, in the case of a string) the top two items on the stack, consuming them and pushing the result.

-

Subtracts the top two items on the stack, consuming them and pushing the result.

*

Multiplies the top two items on the stack, consuming them and pushing the result.

/

Divides the top two items on the stack, consuming them and pushing the result.

I/O Operations

outl

outl outputs the top of the stack with a newline at the end, consuming it.

outf

outf outputs the top of the stack (flush-ly) and consumes it.

chr

If the top of the stack is an integer, chr prints the ASCII value of that integer, consuming it.

getl

getl gets a line of input.

getc

getc gets one character of input.

Goto/Labels

label:<label name>

Creates a label to jump to with goto

goto:<label name>

Jumps to the given label

Conditional statements

=

Checks if the top two items on the stack are equal, consuming them. If they are, it pushes true. Otherwise, it pushes false.

!

Checks if the top two items on the stack are not equal, consuming them. If they aren’t, it pushes true. Otherwise, it pushes false.

<

Checks if the second from top item on the stack is lesser than the top, consuming both. If they are, it pushes true. Otherwise, it pushes false.

>

Checks if the second from top item on the stack is greater than the top, consuming both. If they are, it pushes true. Otherwise, it pushes false.

if-true:<label-name>

If the top is the stack is true, then jump to the given label. Doesn’t consume the top, so it’s good to put drop after it if you don’t neet the boolean there.

if-false:<label-name>

If the top of the stack is false, then jump to the given label. Does not consume the top.

Subroutines

sub:<sub name>

Defines a subroutine with the given name. Everything until -- is the body of the subroutine. Eg, sub:hello    "Hello, world!" outl    --. Recursion is not supported, and labels/gotos inside and outside of the subroutine cannot interact.

call:<sub name>

Calls the given sub

Examples

Just a couple of examples, because it’s nice to have them! 👍

Subroutines

sub:greet
  -> name # Assign the top of the stack to name
  "Hello, &{name}!" outl # Output "Hello, " + the name variable + "!" (Note: interpolation only works with variables)
--

"world" call:greet # This prints Hello, world!

Goto/labels

# Print 'Hello!' forever
label:again # Create a new label called 'again'
"Hello!" outl # Print 'Hello!'
goto:again # Jump to the label 'again'

Conditional/If

"bar" -> foo
foo "bar" = # In this case, it pushes true to the stack, because foo == "bar"
if-true:trueCaseLabel # If the top is true, go to the label trueCaseLabel
if-false:falseCaseLabel # The same, but if false and going to falseCaseLabel
label:trueCaseLabel
    "Foo is bar!" outl
    goto:endFooBarCase
label:falseCaseLabel
    "Foo is not bar!" outl
label:endFooBarCase
drop # Drops the true off of the stack, because if-true and if-false doesn't consume anything, and junk on the stack is bad

Installation

Currently, there is no easy way to install it on a local machine (It’s here, if you want to download it and make an alias or something) but it’s on Replit, so you can play with it there. I’m working on it.