Abstract

From Esolang
Jump to navigation Jump to search
Abstract
Paradigm(s) Imperative
Designed by User:Peter
Appeared in 2022
Memory system Stack-based
Computational class turing-complete
Reference implementation https://github.com/Peter919/Abstract (poorly written C implementation)
File extension(s) .abs

Abstract is a stack-based esoteric programming language designed by me (User:Peter). Code execution and memory management happens in the same stack, and there is no built-in control flow. Variables are simply indices in this stack, and will be replaced by constant integers in compile time. Despite its unusual concepts, Abstract is far from impossible to write complex programs in due to some useful pointer operators.

Language overview

Abstract operates on a single stack of commands, numbers, pointers and strings. Initially, the stack contains variables and the instructions written in the main program.

Instruction pointer

The first element in the stack is a built-in identifier called the instruction pointer, or ip. At first, it points to the first command in the main program, and it will execute commands and go to the next one until it reaches the end of the program. Control flow can be simulated by changing the instruction pointer.

Identifiers

Identifiers in Abstract are simply indices in the stack, and their value can be accessed using pointer commands. Before an Abstract program is executed, the identifiers will be counted and made space for in the beginning of the stack, before being replaced by integers containing the index of those elements. For instance, if the only variable in a program is foo, it will be replaced by the number 1 before code is executed since it's the 1st element in the stack (the 0th element is ip). The value stored in foo can be accessed by using a command to duplicate the foo'th (1st) element of the stack to the top, or it can be changed by using another pointer command. foo itself never changes since it's replaced by 1 in compile time, but the value stored in the 1st element in the stack can.

Instructions

After ip and any identifiers have been pushed onto the stack, all of the instructions in the main program file will be pushed onto the stack before execution starts. The instruction pointer will point to the first of these commands.

Instruction set

Despite being quite simplistic, Abstract has a large instruction set compared to many other esoteric programming languages. Other than some syntactic sugar used to push special values (like strings and instructions), most of the instructions are not easily replaceable and quite straightforward.

Pushing

There are three main ways to push values onto the stack in Abstract:

  • Strings: All characters between two double quotes (") in addition to a null-terminator is pushed onto the stack when encountered by ip. Alternatively, one can use single quotes (') for the same effect without a null-termination, which is useful for pushing single characters.
  • Numbers: Any number encountered by the instruction pointer will be pushed onto the stack as a single element.
  • Code: Code can be pushed onto the stack if it's in between two curly brackets ({ and }). ip can later be made point to these locations, which simulate goto-statements. These types of code blocks can be nested.

Pointer operators

There are three different pointer operators in Abstract:

  • & pushes the index of the top value of the stack, which equals the length of the stack - 1.
  • ! sets the xth value in the stack (from the bottom) to y, where x is the second-from-the-top element in the stack, and y is the top element. It then pops two elements from the stack. For example, 1&! will make the first element in the stack point to the top of the stack by first pushing the number 1, then pushing the index of the stack top (&), and finally making the first element point to that index (!).
  • @ replaces the top element of the stack with the xth element, where x is the value stored in the top of the stack. For instance, ip@ will push the value of ip by first pushing its index and then replacing it with the value stored in that index.

Arithmetics

Abstract has a relatively large set of arithmetic operators: +, -, *, /, % (modulo), ^ (power), log (logarithm), root, sin (sine, radians), cos, tan, asin (arcsine, radians), acos, atan, round, floor, ceil and abs (absolute value). All of these commands performs a mathematical operator on one or two arguments from the top of the stack, pops the arguments and pushes the result. The arguments are in chronological order from the bottom, meaning that operators like - will push the second from the top element minus the top element (that is, after popping the two elements).

Input and output

There are four simple input and output operators in Abstract:

  • , will push each character from the input, including a null-terminator, onto the stack.
  • ; will push the input as a single number onto the stack.
  • . will print a null-terminated string, starting at the address stored in the top of the stack. It will then pop the top of the stack.
  • : will print the top of the stack as a number and pop it.

Special

Here are the commands that doesn't fit into any of the other categories:

  • ~ ends the program when encountered.
  • Square brackets ([ and ]) will be replaced by the contents of the file written within them in compile time. For example, if file.abs contains 2 3 *, 5 [file.abs] + will be replaced by 5 2 3 * +. Square brackets are evaluated after the lexical analysis, so they won't be evaluated if they're inside of comments or strings, and a single token can't be split between two files (so 1[file.abs]3 where file.abs contains 2 will push 1, 2 and 3 - not 123).

External resources