Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.
/ stas Public archive

A stack based compiled systems programming language.

License

Notifications You must be signed in to change notification settings

l1mey112/stas

Repository files navigation

stas - st(ack) as(sembler)

A stack based compiled systems programming language.

include <std.stas>

fn main {
    'Hello world!\n' puts
}

Loosely inspired by FORTH with a modern syntax, stas is a general purpose low level stack based systems programming language. With syntax designed to be short and consise, programs written in stas take a concatenative form. A form where functions and operations mutate the stack in a pipeline where each output is anothers input.

The stas programming language compiler supports x86_64 systems using the Linux and FreeBSD kernels and can cross compile to both with ease. Unencumbered by a C library, stas utilises OS specific native system calls to interact with the system. The full POSIX API and it's definitions are avaliable in the standard library.

This is my first ever programming language and compiler, the initial journey with all of the guesswork has been documented on my blog at tags/stas, these show the small steps taken to achieve initial V version of the compiler. The V source code of the bootstrap compiler is in a-different-branch.

release changelogs

A release changelog is a complete post outlining all additional features added between releases, and if you're lucky, how they are implemented.

programming in stas

Guides created by myself.

As you know, concatenative stack based programming. Think forth. Gloss over these sources.

Comments are denoted with semicolons. Checkout the files/ directory for examples, it contains implementations of rule 110, rule 90 and rule 30, among others and growing.

bootstrapping stas

The-stas-compiler-is-written-in-stas. To avoid the chicken or the egg scenario, precompiled assembly files reside in the bootstrap/ directory.

Use FASM, the flat-assembler, to compile the binaries.

$ fasm -m 1048576 bootstrap/x86-64_linux.fasm.asm stas
$ doas|sudo ./stas symlink
$ stas -h
....
$ ./stas
stas 0.2.0 Copyright (C) 2022  l-m.dev

USAGE: ./stas [OPTIONS] [FILE]

  -o <output>             Specify '-o -' to dump assembly to stdout
  -g                      Debug info. Most effective with the `nasm` backend
  -b <backend>            Assemblers `nasm` or `fasm` as compiler backend
  -c                      Create object file for linking, will not call `ld`
  -r                      Execute file after compiling. Arguments after this
                          switch will ignored and passed to the program
  -v                      Activate verbose mode
  -os <os>                `linux` | `freebsd`
  -dump-tok               Dump token information after scanning stage
  -dump-ir                Dump intermediate representation after parsing stage
  -unsafe                 Currently only strips assertions
  -comptime-depth <num>   Adjust compile time recursion depth for evaluating
                          comptime functions. Default: 12
  -trace-calls            Compiled executable will have function calls traced
                          at runtime. Will not trace inlined calls
  -h, --help              Show this message

SUBCOMMANDS

  ./stas symlink          Will create a symbolic link to the stas compiler
                          inside `/usr/local/bin/stas`

spec

It generates optimised x86-64 assembly for systems using the Linux kernel. It interfaces with the operating system kernel through syscalls and not through libc. The compiler only emits statically linked binaries for now. This means limited portability among other operating systems and architectures.

The stas compiler generates decently optimised assembly by converting stack based operations to ones that work register to register. It does this through the register-allocator present in the compiler.

A dead code elimination pass takes place between the parser and code generation passes. Here, it is also determined which functions will be automatically inlined. Inlining a function removes the overhead of switching between the return stack and the data stack during a function call. The DCE pass also handles optimising tail recursion calls.

  (text)     |  (tokens)         (IR)            (assembly)      | (ELF/assembly)
             |                                                   |
             |             /-- parser  --\   /--- codegen ----\  |
 input.stas ->- scanning - |             | - |                | ->- backend
             |             \-- checker --/   \- optimisation -/  |

IDE support

Currently, only a Visual Studio Code extension exists supporting syntax highlighting. Freely avaliable in the vscodium extension store, download a copy from open-vsx.