Allow compilation to include .a, .c, and .o files alongside .sunder files
Add fine-grained lookup functions to std::hash_map and std::hash_set
Write the std::string NUL terminator in std::string::resize rather than std::string::cstr
Sunder is a C-like systems programming language and compiler for x86-64 and ARM64 Linux.
Sunder tooling should build and run on any x86-64 or ARM64 Linux machine satisfying the following dependencies:
make
c99
, clang
, gcc
, etc.)ld
clang
or gcc
(C backend only)nasm
or yasm
(x86-64 NASM backend only)clang-format
(development only)The top-level Dockerfile defines a Debian image with all development dependencies pre-installed. The Docker image can be built and run with:
$ docker buildx build --platform=linux/amd64 --tag sunder . # Build the image (do this once)
$ docker run --rm --interactive --tty --volume "$(pwd)":/sunder sunder # Run the image (do this every time)
Run make
to build the compiler.
Run make check examples
to run the test suite and compile the example
programs under the examples
directory.
The top-level Makefile
contains the following important targets:
build
=> Build the compiler (default make
target).check
=> Run the test suite for the language and standard library.examples
=> Compile the example programs under the examples
directory.format
=> Run clang-format
over the compiler sources.clean
=> Remove build artifacts.Targets will execute with CC=c99
using release mode CFLAGS
by default.
Specific compiler/compiler-flag combinations include:
$ make <targets> CFLAGS='$(C99_DBG)' # POSIX c99 (debug)
$ make <targets> CFLAGS='$(C99_REL)' # POSIX c99 (release)
$ # Use CC=clang for Clang or CC=gcc for GCC
$ make <targets> CC=clang CFLAGS='$(GNU_DBG)' # clang/gcc (debug)
$ make <targets> CC=clang CFLAGS='$(GNU_DBG) $(SANITIZE)' # clang/gcc (debug with Address Sanitizer)
$ make <targets> CC=clang CFLAGS='$(GNU_REL)' # clang/gcc (release)
The compiler is built with SUNDER_DEFAULT_BACKEND=C
and
SUNDER_DEFAULT_CC=clang
by default, indicating that the C backend should be
used with clang
if SUNDER_BACKEND
and/or SUNDER_CC
(explained below) are
not set when the compiler is invoked.
To use nasm
as the default compiler backend, override
SUNDER_DEFAULT_BACKEND
with nasm
when executing targets:
$ make <targets> SUNDER_DEFAULT_BACKEND=nasm
To use yasm
as the default compiler backend, override
SUNDER_DEFAULT_BACKEND
with yasm
when executing targets:
$ make <targets> SUNDER_DEFAULT_BACKEND=yasm
The install
target will install the Sunder toolchain into the directory
specified by SUNDER_HOME
(default $HOME/.sunder
). Run make install
with
SUNDER_HOME
specified as the directory of your choice:
$ make install # Install to the default $HOME/.sunder
$ make install SUNDER_HOME=/opt/sunder # Install to /opt/sunder
Then, add the following snippet to your .profile
, replacing $HOME/.sunder
with your chosen SUNDER_HOME
directory if installing to a non-default
SUNDER_HOME
location:
export SUNDER_HOME="$HOME/.sunder"
if [ -e "$SUNDER_HOME/env" ]; then
. "$SUNDER_HOME/env"
fi
Verify that the compiler has been successfully installed by running
sunder-compile -h
. You may have to source your .profile
in new shells until
the start of your next login session.
Sunder programs are compiled into executables with sunder-compile
.
import "std";
func main() void {
std::print_line(std::out(), "Hello, world!");
}
$ sunder-compile -o hello examples/hello.sunder
$ ./hello
Hello, world!
The -o OUT
option may be used to specify the name of the output executable.
If this option is not provided then the output executable will default to the
name a.out
.
The intermediate files OUT.tmp.asm
, OUT.tmp.c
, and OUT.tmp.o
(output
executable name plus tmp.asm
, tmp.c
, and tmp.o
extensions) are generated
during compilation (depending on the chosen SUNDER_BACKEND
) and subsequently
removed after the output executable has been created. The -k
flag will
instruct the compiler not to remove these files (useful for debugging).
$ SUNDER_BACKEND=C sunder-compile -k -o hello examples/hello.sunder
$ ls hello*
hello hello.tmp.c
$ SUNDER_BACKEND=nasm sunder-compile -k -o hello examples/hello.sunder
$ ls hello*
hello hello.tmp.asm hello.tmp.o
The following environment variables affect compiler behavior:
SUNDER_BACKEND
=> Selects the backend to be used for object file
generation. Currently, SUNDER_BACKEND=C
, SUNDER_BACKEND=nasm
, and
SUNDER_BACKEND=yasm
, are supported. If this environment variable is not
set, then the default backend is used.SUNDER_SEARCH_PATH
=> Colon-separated list of directories specifying the
module search path for import
and embed
statements.SUNDER_SYSASM_PATH
=> Location of the platform specific sys.asm
file that
defines the program entry point as well as low-level operating system and
hardware abstractions when using the NASM backend. If this environment
variable is not set, then the default path is used.SUNDER_CC
=> Selects the C compiler to be used when compiling with the C
backend. Currently, SUNDER_CC=clang
and SUNDER_CC=gcc
are supported. If
this environment variable is not set, then the default C compiler is used.SUNDER_CFLAGS
=> Space-separated list of additional flags passed to the C
compiler when compiling with the C backend.Sunder can be used for scripting by adding #!/usr/bin/env sunder-run
(or
equivalent) as the first line of a Sunder source file. If this environment
variable is not set, then the default path, $SUNDER_HOME/lib/sys/sys.asm
,
is used.
#!/usr/bin/env sunder-run
import "std";
func main() void {
std::print(std::out(), "What is your name?\n> ");
var result = std::read_line(std::input());
if result.is_error() {
std::print_line(std::err(), result.error().*.data);
std::exit(std::EXIT_FAILURE);
}
var optional = result.value();
if optional.is_empty() or countof(optional.value()) == 0 {
std::print_line(std::err(), "unexpected empty input");
std::exit(std::EXIT_FAILURE);
}
var line = optional.value();
defer std::slice[[byte]]::delete(line);
var name = std::ascii::view_trimmed(optional.value());
std::print_format_line(std::out(), "Nice to meet you {}!", (:[]std::formatter)[std::formatter::init[[typeof(name)]](&name)]);
}
$ ./examples/greet.sunder
What is your name?
> Alice
Nice to meet you Alice!
Executing the following commands will create an environment sufficient for Sunder development and experimentation without requiring the Sunder toolchain to be installed.
$ cd /your/path/to/sunder
$ make
$ SUNDER_HOME="$(pwd)"
$ . ./env
$ sunder-run examples/hello.sunder
Hello, world!
Sunder is distributed under the terms of the Apache License (Version 2.0).
See LICENSE for more information.