less_retarded_wiki/comun.md
2024-08-27 17:09:58 +02:00

7.1 KiB

Comun

{ UPDATE: I am currently thinking about reworking comun a bit, maybe drop the whole bytecode and build it more with the incremental style of Forth. I will probably need a lot more time to think it through, please be patient :-) ~drummyfish }

Comun is a beautiful, experimental minimalist programming language made by drummyfish in 2022, based on his ideals of good, selfless technology known as less retarded software (LRS) -- it is still a very much work in progress and may potentially change a lot. It was planned that in the future it should gradually replace C as the preferred LRS language, however it's very soon for this still. The language has been inspired mainly by Forth but also C, brainfuck and other ones. Though already usable, it is still in development; currently there is a suckless implementation of comun in C as well as a basic self hosted one which can bootstrap itself and should gradually replace the C version. There is also a number of supplemental materials such as a specification, tutorial and some example programs. The project repository is currently at https://codeberg.org/drummyfish/comun. The aim now is to make a self hosted implementation, i.e. write comun in comun.

How minimal is comun? The specification fits on one sheet of A4 paper (using both sides) and the minimal self hosted compiler without preprocessor and fancy features has some 2400 lines of code, a lot of which are documenting comments (the whole self hosted codebase that also includes a more "feature rich" compiler, optimizer, interpreter etc. still has fewer than 5000 lines).

{ NOTE: I found a language on esolang wiki called Minim that looks a bit similar to comun, however it looks a bit sucky. Anyway it should be researched more. ~drummyfish }

The language is intended to be the foundation of a completely new, non-capitalist computer technology built from the ground up, which should culminate in the creation of the LRS much desired public domain computer. This technology is derived from the model of an ideal society and as such will aim for completely different goals (such as helping all living beings as much as possible without enslaving them) and values; this makes comun astronomically different in philosophy and design of the shitty, toxic capitalist joke languages such as C++ and Rust which pursue fascism, enslavement of humans to the productivity cult etc.

Comun is planned to closely interact with comun shell, though the two parts will be completely independent.

A quick sum up is following: comun is minimalist, low level with minimum abstraction, portable, imperative and stack-based, using reverse Polish notation. It can be both compiled and interpreted. There are only primitive integer data types (native integer size by default with possibility to specify exact width where necessary, signed/unsigned interpretation is left to the programmer) and optional pointers that can be used as variables, for managing multiple stacks, creating arrays etc. Its specification can fit on a sheet of paper and is completely public domain under CC0 (as is its current implementation). It has no standard library. There are no English keywords; commands are rather very short (mostly 1 to three symbols) math-like symbols. Source code only allows ASCII symbols (no unicode). There is an optional preprocessor that uses comun itself (i.e. it doesn't use any extra language). Functions and recursion are supported. Many features of the language are optional and never burden the programmer if he doesn't use them. Simplified versions of the language (minicomun and microcomun) are also specified. The only I/O in pure comun is standard input and standard output, i.e. there is no input/output from/to files, screen, network etc., the language merely processes input values into output values -- handling more complex I/O is left for libraries and/or comun's wrapping environment, such as comun shell.

TODO: compare to Forth

Examples

Here is a very short showcase of comun code, demonstrating some common functions:

max: <' ? >< . ^ .      # takes maximum of two values

max3: max max .         # takes maximum of three values

# recursive factorial
factR:
  ?'
    $0 -- factR *
  ;
    ^ 1
  .
.

# iterative factorial
factI:
  $0 --

  @'
    >< $1 * ><
    --
  .
  ^
.

The following is a quine in comun:

0 46 32 34 S 34 32 58 83 S --> S: "0 46 32 34 S 34 32 58 83 S --> " .

The following code translates brainfuck to comun (proving comun really is Turing complete):

0 "$>0 " -->

@@
  <? ?
    <- 

    $0 "+" = $1 "-" = | ?
      $0 -> $0 -> " " ->
    .

    $0 "<" = $1 ">" = | ?
      "$" -> $0 -> "0" -> " " ->
    .

    $0 "." = ?
      0 "->' " -->
    .

    $0 "," = ?
      0 "$<0 <- " -->
    .

    $0 91 = ? # left bracket
      0 "@' " -->
    .

    $0 93 = ? # right bracker
      0 ". " -->
    .

    ^
  ;
    !@
  .
.

The following is our standardized divisor tree program written in comun:

# pops a number (< 1000) and prints it
numPrint999:
  $0 99 > ? $0 100 / "0" + -> .
  $0 9 > ?  $0 10 / 10 % "0" + -> .
  10 % "0" + ->
.

# converts single digit to number (or -1 if invalid)
digitToNum:
  $0

  $0 "0" >= >< "9" <= & ?
    "0" -
  ;
    ^ -1
  .
.

# takes x, pops it and recursively prints its divisor tree
printDivisorTree:
  -1 -1                 # divisors: a, b

  $2 2 / @@             # for i = x / 2
                        # stack now: x a b i
    $0 1 <= ?
      !@
    .

    $3 $1 % 0 = ?       # i divides x?
      $0 $:3            # a = i
      $3 $1 / $:2       # b = x / i

      $2 $2 <= ?        # a <= b?
        !@
      .
    .

    --                  # decrement i
  .
  ^                     # pop i

  "(" ->

  $0 -1 != ?
    printDivisorTree
    " " ->
    >< numPrint999      # print x
    " " ->
    printDivisorTree
  ;
    ^ ^                 # pop a, b
    numPrint999
  .

  ")" ->
.

@@                      # read numbers from the user
  0 10 "enter a number:" -->

  0                     # x
  @@                    # read x
    <-
    $0 10 = ? ^ !@ .    # newline?
    digitToNum
    $0 -1 = ? !. .      # wrong digit? then end
    >< 10 * +
  .

  $0 1000 < ?           # x < 1000?
    printDivisorTree
    10 ->               # newline
  ;
    !@
  .
.

See Also