项目作者: cassaundra

项目描述 :
Columnar esolang inspired by Befunge and Brainfuck
高级语言: Rust
项目地址: git://github.com/cassaundra/col.git
创建时间: 2019-03-24T21:44:50Z
项目社区:https://github.com/cassaundra/col

开源协议:MIT License

下载


col

col is an esoteric programming language inspired by classical architectural columns and the syntax of other esolangs like Befunge and Brainfuck.

Both the instruction sets and the memory stacks are interpreted as columns. Each column can perform a variety of operations on its own stack, as well as push and pop to/from another column’s stack. Below is a more visual representation of this general structure. The finite source code is written at “base” of the column, while the memory stack of each column spans the shaft (length).

  1. ┌─ #4
  2. 5 0
  3. 4 1
  4. 3 7 0
  5. 2 5 v 1
  6. 1 3 0 1) Instructions are executed
  7. 0 1 6 1 <- #2 from top to bottom
  8. ─── ─── ─── ─── ... 2) Bottom of memory stack
  9. a d g j <- #1 3) Column currently being executed
  10. b e h k 4) Selected remote memory stack
  11. c f i l
  12. ^
  13. #3

The source of the above program would be:

  1. abc
  2. def
  3. ghi
  4. jkl

Interpreter

This repository contains col’s interpreter. Its only direct dependencies are rand and clap, for all you purists out there! (:

Compile it with cargo build --bin coli --release, and run the interpreter on a file with cargo run --bin coli --release -- file.col. Check the --help for more information.

You can also use col as a library in your own project. See the crate documentation for more details.

Theory

There aren’t clear assurances of immutability or privacy in a col program, as any column may read and/or modify another column’s stack. In traditional programming, this would be dangerous, but it’s an intentional design choice in col. The accessibility of memory is unrestricted, but there are still clearly defined associations between instructions sets and their memory.

Furthermore, “functions” (instruction sets) may have memory that persists longer than a single execution. The programmer may choose to clear the memory stack as if it’s scoped, or allow it to persist through future iterations, or a hybrid of both. As a result, the line between persistent and ephemeral memory is blurred.

Specification

Rules

  • When an instruction stack has completed execution, it repeats.
  • Each column may switch its “remote” stack, which is by default itself (so ^, v, and s yield no change).
  • There are a finite number of executable columns as defined by the program source. However, you may use any remote column as a memory stack, even if there is not a corresponding line in the source.
  • Lines (separated by line feeds) represent columns, where the line index maps to the column index (e.g. first line is column #0). Leading and trailing empty lines are ignored.
  • Undefined characters (including whitespace) are ignored by the interpreter unless in string mode.
  • The columns are organized conceptually as a circle, wrapping at either end.
  • The runtime user’s input is also represented as a stack.
  • If any operation cannot be performed, the value zero is used instead.
    • Dividing by zero results in zero being pushed to the local stack.
    • Attempting to pop a value from an empty stack (whether it be local, remote, or user input) results in zero being returned instead.
  • The defined remote stack of a column persists between executions.
  • The program terminates only upon the terminator character, @.

Implementation

There are certain aspects of col that are left up to implementation:

  • Max stack size
    • Default: unlimited
  • Max number of columns
    • Default: 4294967296 (2^32)
  • Charset
    • Default: UTF-8
  • Value type
    • Default: unsigned 32-bit integer

Ideally the max value would be greater than or equal to the number of columns, so the ; and ~ commands can be used for every column.

Instructions

Cmd Description
< Push the index of the column on the left to the local stack.
> Push the index of the column on the right to the local stack.
. Push the index of the current column to the local stack.
; Pop value a and begin execution at the ath column.
~ Pop value a and set the remote stack to the ath column’s stack.
^ Pop value a from the local stack and push to the remote stack.
v Pop value a from the remote stack and push to the local stack.
\ Swap the top two values of the local stack.
: Duplicate the top value of the local stack (peek + push).
x Discard the top value of the local stack.
c Clear the local stack.
s Swap the local and remote stacks.
r Reverse the order of the local stack.
0-9 Push a number value to the stack (not the UTF-8 value of the digit).
A-F Push a number value to the stack from hexadecimal (decimal 10-15).
[ Skip past the matching ] if the top value (peek) a is zero. If none found, then the IP will return to the start.
] Skip back to after the matching [ if top value (peek) a is non-zero. If none found, then the IP will return to the start.
+ Pop values a and b and push the result of a plus b.
- Pop values a and b and push the result of b minus a.
* Pop values a and b and push the result of a times b.
/ Pop values a and b and push the integer result of b divided by a. If a is zero, then zero will be pushed to the stack.
% Pop values a and b and push the remainder of the integer division of b divided by a.
= Pop values a and b, and push one if a equals b, and zero otherwise.
` Pop values a and b and push one if b is greater than a, and zero otherwise.
, Pop values a and b and push the bitwise NAND result of the two.
& Pop values a and b and push one if they’re both non-zero, and push zero otherwise. Not a bitwise AND.
`\ ` Pop values a and b and push one if at least one is non-zero, and push zero if they are both zero. Not a bitwise OR.
! Invert the top value of the local stack. If it’s zero, push one, and if it’s non-zero, push zero.
? Push a random value to the local stack
" Toggle string mode and push UTF-8 values until next ".
_ Pop UTF-8 char from user input and push to the stack. If no more are available, push zero.
$ Pop a and print its UTF-8 value.
# Pop a and print its numeric value.
p Print all values in stack (from top to bottom) as UTF-8 characters.
@ Terminate the entire program.

Examples

Hello world:

  1. "Hello, world!"Arp@

Fibonacci:

  1. 11#>;
  2. A$2~v0~v2~:^+::0~^#

Quine:

  1. " r:2+p@

TODO

Interpreter:

  • Improve performance, I/O is a notable bottleneck
  • Improve char parsing
  • Add more unit tests
  • Decide on a program state implementation
  • Use generics to allow deviations from the unsigned 32-bit default type