Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Welcome to the Solstice documentation! Here we have a tutorial (starting here) and a specification for the Solstice programming language.

If you’re new to Solstice, I’d recommend starting the tutorial, at the installation page. If you’ve already installed Solstice, start at the Basics page.

Found a mistake? Report it at https://chookspace.com/solstice/docs

Docs generated by mdBook.

Installation

Solstice is fully supported and tested on Linux, however should work on most UNIX-like environments. Windows support is theoretically possible, however not all features are avaliable, so use WSL, MSys, or Cygwin instead.

Which method is for you?

Use a prebuilt binary if you’re in a rush, or you can’t get a compiler on your system.

Use the automated build script for a full install of Solstice and Ground, with maximum flexibility.

Do a manual build if you intend to contribute to the Solstice source code.

Prebuilt Binaries

Solstice binaries statically linked with Ground are avaliable from the Solstice releases page. For now, these are only for Linux x86_64, but more options may be avaliable in future.

Download the latest release, copy it into a folder in your path (such as /usr/local/bin) and enjoy!

Producing release binaries

There is a script on Chookspace which builds Solstice and Ground in a container. Use this script for building production releases, and determining whether bugs are setup-specific or affect all people.

Use this script to produce prebuilt binaries for the releases page.

Build dependencies

macOS

xcode-select --install

Then, download UTHash here, and copy the contents of the include folder to /usr/local/include:

sudo cp (/path/to/uthash-master)/include/* /usr/local/include

Ubuntu/Debian

sudo apt install gcc git make uthash-dev

Arch Linux

sudo pacman -S --needed gcc git make uthash

Automated Build Script

This method requires the following installed:

  • uthash (in /usr/include or similar)
  • A gcc-compatible C compiler linked to cc
    • GCC and Clang are both tested and will yield similar results.
  • Git (to get source code)
  • Make (to organise building the code)

Refer to Build Dependencies for instructions on how to install dependencies.

Running the installer

Run this command in your terminal:

bash -c "$(curl -fsSL https://sols.dev/install.sh)"

This will:

  • Download a shell script from https://sols.dev/install.sh
  • Run the contents of the shell script in the bash command interpreter

The script does the following:

  • Checks if Ground and Solstice are installed on your system.
  • If either Ground or Solstice aren’t avaliable, it will download, build, and install the source code.
  • If Ground or Solstice are installed, it will update them to the latest version.

Building Manually

Refer to Build Dependencies for instructions on how to install dependencies.

Build and install Ground:

git clone https://chookspace.com/ground/ground
cd ground
make
sudo make install
cd ..

After this, build and install Solstice:

git clone https://chookspace.com/solstice/solstice
cd solstice
make
sudo make install
cd ..

Command Usage

Solstice programming language
Usage: solstice <file> [-h] [--help] [-p] [--print] [-b <file>] [--bytecode <file>] [-c <file>] [--compile <file>]
Args:
  <file>:                         Solstice source file
  -h or --help:                   Prints this help message and exits
  -p or --print:                  Prints textual version of Ground bytecode to console
  -b <file> or --bytecode <file>: Generates Ground bytecode (.grbc) and saves it to the provided filename
  -c <file> or --compile <file>:  Compiles Ground to Linux x86_64 assembly, outputs a binary to the provided filename (experimental)
  If no extra arguments are provided, the generated Ground bytecode will be executed.

Arguments:

<file>

The Solstice source file to run.

There should never be more than one file, as Solstice allows files to import each other, rather than compiling multiple files into one manually.

-h or --help

Shows the help message above.

-p or --print

Prints the textual version of the generated Ground bytecode to the console.

This is useful for debugging the compiler, and ensuring the correct output is produced for the GroundVM.

-b <file> or --bytecode <file>

Outputs Ground bytecode (in grbc format) and saves it in the file <file>.

Ground bytecode is useful for distributing software in a format where the target machine does not need Solstice installed, only the Ground VM.

Run the compiled bytecode with:

ground -b <file>

-c <file> or --compile <file>

Compiles the Ground bytecode to assembly using the Tram backend, outputting a binary named <file>.

Requires Ground to be built with Tram support, and Tram to be installed on your system.

This backend is experimental and does not support all features.

Basics

This part of the tutorial shows you the basics of using Solstice. Click next to see the “Hello, World!” program!

Hello, World!

Create a new file on your computer (preferably in a new folder) named main.sols. In the file, write the following:

puts "Hello, World!"

Save the file, then run in your terminal:

solstice main.sols

Solstice will run the file for you, which should print Hello, World! to the console.

Here’s what it does:

  • puts: Stands for “put something”. It’s Solstice’s built in “please print out this thing’s current state” operator.
  • "Hello, World!": A string. A string is a collection of characters. In Solstice, you denote a string by surrounding your text with double quotes (").

Next up: using variables!

Variables

Creating Variables

In Solstice, you can initialize a variable using the syntax:

name = value

where:

  • name is the name of your variable. You can use all letters in variable names, as well as underscores and numbers.
    • The standard way to name your variables in Solstice is with camelCase.
  • value is some sort of value. This value can be:
    • an integer (number with no decimal place)
    • a double (number with a decimal place)
    • a string (collection of characters, as seen before)
    • a character (a single letter)
    • a boolean (either true or false)

We’ll look at types of values soon.

Recalling Variables

Recall a variable’s content by using it’s name:

puts name

where name is the name of your variable.

Comments

In Solstice, there are 3 ways to do comments:

// (Single-Line Comment)

Writing // tells Solstice to ignore the rest of the line.

Some examples:

puts 2 + 2 // should be 4

// This variable holds the status code from checkStatus()
statusCode = checkStatus("file.txt")

This comment should be used when writing your code’s logic in Solstice.

/* */ (Multiline Comment)

Any text in between /* and */ will be ignored. These comments should be used to document functions and structs (we’ll get to those later.)

Example:

/*
    Adds two numbers together.
*/
def add(int a, int b) int {
    return a + b
}

# (Shebang Comment)

Use this comment only for using Solstice as a script interpreter in a shebang. Effectively the same as //, but we recommend using // over #.

Values and Types

In Solstice, everything is a value, and every value has a type. Values can be moved around and passed to different functions, however to pass them around their type must be confirmed.

int

An int is a signed (meaning either positive or negative) 8-byte integer (meaning no decimal place).

Using this size, Solstice can accurately process numbers between -9,223,372,036,854,775,807 and 9,223,372,036,854,775,807.

Integers are represented as a collection of digits not seperated by anything, such as:

123
7483
423843269

double

A double is a signed 8-byte floating-point (meaning with a decimal place) number.

Using this size, Solstice can accurately process numbers between 15 and 17 digits long.

Doubles are represented as a collection of digits, with a dot (.) seperating the ones and tenths positions, such as:

3.14
432.543
5907432.432

string

A string is a collection of characters which end with a null byte (handled by Solstice).

Solstice can accurately process strings of any size, provided your computer has enough memory.

Strings are represented as a collection of characters surrounded by double quotes (""), such as:

"Hello, World!"
"Solstice is cool"
"Rust kinda mid"

char

A char is a signed 1-byte integer, represented as an ASCII character, however can also be used to represent a single byte in a stream.

Solstice can accurately process any ASCII character.

Characters are represented as a single character surrounded by single quotes (''), such as:

'a'
'b'
'c'

bool

A bool is a variable which can either be true or false.

true
false

Other Types

Solstice has three other types: fun, template, and object, but we’ll cover these in the Functions and Structures pages.

Functions

Defining Functions

In Solstice, functions are a way to organise and reuse code. Here’s an example function:

def add(int a, int b) int {
    return a + b
}

Here’s what each part is:

  • def: Means “define”. Tells Solstice we are defining a function.
  • add: This is your function name! Choose something unique.
  • (int a, int b): These are the arguments your function takes.
    • Enclose your argument type and name pairs in brackets.
    • The first identifier should be a type (such as int, string, etc), the second should be an identifer
    • After each type-name pair, add a comma unless you’ve got no more arguments to define
  • int: This is your return type
  • return a + b: This is where your code goes for the function

Calling Functions

Call a function in Solstice like this:

myFunction(a, b, c)

where:

  • myFunction is the name of your function
  • (a, b, c) are the arguments you would like to pass to the function.
    • Enclose the arguments in parentheses (( ))
    • Each argument should be seperated by a comma
    • Solstice will type-check each argument to ensure it matches the function’s specified types

Closures and Scoping

Each function has an attached closure, which is the state captured at runtime when the function is defined. All variables in the closure can be accessed inside the function body, however the closure cannot be modified (meaning all variables captured remain consistent across function runs).

This behaviour ensures that functions are not affected by global state, and will always have reliable, consistent behaviour.

Additionally, all defined arguments are avaliable in scope.

x = 10

def myFunction() int {
    // Here, x is avaliable, however if we modify it,
    // our changes won't affect the external state, or
    // the state of this function when it runs.
    puts x
    x = 5
    return x
}

myFunction() // returns 5, prints 10
myFunction() // returns 5, prints 10

puts x // prints 10, x has not been modified by myFunction

The type of a function

If you’d like to accept a function as an argument, you need to specify it’s type signature. That can be done like this:

fun(int, string) bool

where:

  • fun tells Solstice we’re writing a type signature for a function
  • (int, string) is the list of argument types (names are not needed), seperated by commas, surrounded by brackets
  • bool is the return type

making this type represent a function which takes an int and a string, and returns a bool.

Structures

Naming Conventions

Comment Conventions

Code Layout

Reserved Words

This is a list of all reserved words in Solstice, seperated by new lines. These words may not be used as identifiers.

After //, notes may be provided which detail exceptions to the reserved word, however, the word should still be treated as reserved regardless.

puts
if
while
def
lambda
return
use
struct
enum
constructor
destructor
duplicator
private
protected
ground      // Only when targeting GroundVM
new
as
sizeof
pragma

fun
template
object

Comments

Comments in Solstice can be done in 3 ways:

// (Single-Line Comment)

Use // to tell Solstice to ignore text until the end of the line.

This kind of comment should be used inside code to explain how parts of code work.

/* */ (Multiline Comment)

Use /* and */ to tell Solstice to ignore text in between the two markers.

This kind of comment should be used for explainations of how functions and structs work, placed above the definition.

# (Shebang Comment)

Use # to tell Solstice to ignore text until the end of the line.

This kind of comment should be used in a shebang (writing #!/usr/bin/env solstice at the top of your entry point source file), not in the middle.

Example

#!/usr/bin/env solstice

/*
    This function does something.
    Input:
        funnyNumber: A funny number
    Returns: Another funny number
*/
def doSomething(int funnyNumber) int {
    // Tell the user the number is funny
    puts "The number" funnyNumber "is very funny"

    // Now give them another funny number
    return 532
}

Expressions

An expression in Solstice is a combination of operators and values (whether literal or stored in a variable).;

Expression Types

“Precedence” is a number which dictates the order of execution. The higher the precedence, the sooner an expression will be evaluated.

Binary Mathematical

  • +: Adds two numbers on either side, or concatenates two strings
    • Accepts:
      • Two integers either side
      • Two doubles either side
      • Two strings either side
      • An integer and a double on either side (order not significant)
    • Returns:
      • The sum of both values as an integer if both values are integers
      • The sum of both values as a double if one value is a double and the other is an int, or both values are doubles
      • The concatenated string when both values are strings
    • Precedence: 5
  • -: Subtracts two numbers on either side
    • Accepts:
      • Two integers either side
      • Two doubles either side
      • An integer and a double on either side (order not significant)
    • Returns:
      • The difference of both values as an integer if both values are integers
      • The difference of both values as a double if one value is a double and the other is an int, or both values are doubles
    • Precedence: 5
  • *: Multiplies two numbers on either side
    • Accepts:
      • Two integers either side
      • Two doubles either side
      • An integer and a double on either side (order not significant)
    • Returns:
      • The product of both values as an integer if both values are integers
      • The product of both values as a double if one value is a double and the other is an int, or both values are doubles
    • Precedence: 6
  • /: Divides two numbers on either side
    • Accepts:
      • Two integers either side
        • Two doubles either side
          • An integer and a double on either side (order not significant)
    • Returns:
      • The quotient of both values as an integer if both values are integers
      • The quotient of both values as a double if one value is a double and the other is an int, or both values are doubles
    • Precedence: 6

Binary Comparative

  • ==: Checks two values to determine if they are equal
    • Accepts:
      • Any two values either side which are of the same type
      • An integer and a double on either side (order not significant)
    • Returns:
      • true if both provided values are exactly the same.
      • false otherwise.
    • Precedence: 2
  • !=: Checks two values to determine if they are not equal
    • Accepts:
      • Any two values either side which are of the same type
      • An integer and a double on either side (order not significant)
    • Returns:
      • true if both provided values are not exactly the same.
      • false otherwise.
    • Precedence: 2
  • >: Checks two numbers to determine which is greater
    • Accepts:
      • Any two numbers (int or double) either side
    • Returns:
      • true if the number provided on the left is greater than the number provided on the right.
      • false otherwise.
    • Precedence: 2
  • <: Checks two numbers to determine which is lesser
    • Accepts:
      • Any two numbers (int or double) either side
    • Returns:
      • true if the number provided on the left is lesser than the number provided on the right.
      • false otherwise.
    • Precedence: 2
  • >=: Checks two numbers to determine which is greater, or whether both are equal
    • Accepts:
      • Any two numbers (int or double) either side
    • Returns:
      • true if the number provided on the left is greater than the number provided on the right, or if both numbers are equal.
      • false otherwise.
    • Precedence: 2
  • <=: Checks two numbers to determine which is lesser, or whether both are equal
    • Accepts:
      • Any two numbers (int or double) either side
    • Returns:
      • true if the number provided on the left is lesser than the number provided on the right, or if both numbers are equal.
      • false otherwise.
    • Precedence: 2

Binary Misc

  • as: Converts between types.
    • Accepts:
      • Any object on the left, and a type which has an applicable conversion defined by the object on the right
    • Returns:
      • The object turned into the type on the right, in the way defined by the as-method
  • .: Accesses object fields
    • Accepts:
      • An object on the left, and an identifier on the right which corresponds to a field or method in the object
    • Returns:
      • The object field or method the identifier corresponds to

Brackets

  • (...): Evaluates an expression inside the brackets before outside expressions.
    • Accepts:
      • Any expression inside the brackets (in place of ...)
    • Returns:
      • The result of the expression in the brackets
    • Precedence: 7

Function Call

  • (...): Calls the specified function.
    • Accepts:
      • An identifier for the function before the brackets, then comma-seperated expressions corresponding to the function type signature (see Types -> Combined Types -> fun) inside the brackets (in place of ...)
    • Returns:

Unary Misc

  • new: Creates a new object from a template.
    • Accepts:
      • A template after the new keyword.
      • A core type identifier
    • Returns:
      • An object based on the provided template, if provided with a template.
      • The empty version of the core type, if provided with a core type, which is:
        • int: 0
        • double: 0.0
        • string: ""
        • char: '\0'
        • bool: false
  • sizeof: Gets the size of something.
    • Accepts:
      • A string
      • An object with an int size field
    • Returns:
      • The string length if provided a string
      • The int size field of the object if provided an object

Types

Solstice is statically typed, meaning all values must have a known type before any code can be executed.

Core Types

These core types are automatically avaliable in Solstice. The words to identify them are reserved and cannot be reassigned.

int

8-byte signed integer, equivalent to C int64_t or Ground -int.

Examples: 32, 121, -5

double

8-byte double prescision floating point number, equivalent to C double or Ground -double.

Examples: 3.14, -2.7

string

C-style null-terminated array of characters. Equivalent to C char* or Ground -string.

char

1-byte signed integer, usually used to store a character, however can also be used to store bytes. Equivalent to C char or Ground -char.

bool

1-byte unsigned integer, either 1 or 0. Represented by the reserved words true and false. Equivalent to C char (no stdbool.h) or bool (with stdbool.h) or Ground -bool.

Combined Types

These types utilise core types to create new combinations. They take type arguments.

fun

Represents a function. Equivalent to Ground -function, or a C function pointer.

Syntax:

fun(...) type

where:

  • type is a type identifier, which will be the return type
  • ... is multiple type identifiers, seperated by commas, which are the argument types

Example:

fun(int, string) bool

This represents a function which takes an int and string as arguments, and returns a bool.

template

Represents an uninitialized object. Equivalent to Ground -struct.

Syntax:

template(...)

where ... is multiple pairs of:

  • a type identifier for the field, and
  • an identifier (representing the field name)

seperated by commas.

Example:

template(int x, string y)

This represents a template which, when initialized, has fields x (with integer) and y (with string).

object

Represents an initialized object.

Syntax:

object(...)

where ... is multiple pairs of:

  • a type identifier for the field, and
  • an identifier (representing the field name)

seperated by commas.

Example:

object(int x, string y)

This represents a object which has fields x (with integer) and y (with string).

Variables

Variables are defined and modified with the syntax:

name = value

where:

  • name is an identifier, and
  • value is a literal, expression, or identifier previously assigned to a variable.

All variables must have a known type and value at definition time. When updating a variable, the type may not change.

Scoping and Lifetimes

Subscoping

A “subscope” is a scope contained inside a function, created inside curly braces ({}).

Subscopes can view and modify variables avaliable in their parent scope.

Subscopes may also create their own variables, however these will be destroyed when the subscope ends.

Function Scoping

A function scope is a scope created inside a function.

Function scopes are created from a function’s attached closure, which is a snapshot of all variables at the time of function definition.

The function’s attached closure cannot be modified.

Function scopes also contain all arguments provided to a function.

When the function finishes running (with a return), all variables are destroyed.

Destructors

Objects (see here) can contain a destructor which specifies custom behaviour for destroying itself. This is useful for:

  • Freeing heap-allocated memory
  • Closing a connection
  • Closing a file

The destructor will always be in the field destructor with type signature fun() int. It should be automatically called when the variable goes out of scope.

Duplicators

Objects (see here) can contain a duplicator which specifies custom behaviour for copying itself. This is useful for:

  • Duplicating heap-allocated memory

The duplicator will always be in the field duplicator with type signature fun((self) old) (self). It should be automatically called when the variable is:

  • Copied into a new variable
  • Put inside a closure
  • Passed to a function

Operators

Operators are bits of code intended to control how the program runs.

puts

Stands for “put something”. Prints debug info to the console, followed by a new line.

Formatting

  • int: The literal number, as formatted by C printf("%" PRId64).

  • double: The literal number, as formatted by C printf("%f").

  • string: All characters in the string, as formatted by C printf("%s").

  • char: The ASCII character corresponding to the number held, as formatted by C printf("%c").

  • bool: If true or 1, print true. Otherwise, print false.

  • fun: Print <function>.

  • template: Print <struct fields: { ... }>, where:

    • ... is a comma-seperated sequence of key: value, where:
      • key is the identifier of the field.
      • value is the properly formatted value in the field.
  • object: Print <object fields: { ... }>, where:

    • ... is a comma-seperated sequence of key: value, where:
      • key is the identifier of the field.
      • value is the properly formatted value in the field.

if

Runs a block of code only if the provided condition is true.

Syntax:

if condition {
    ...
}

where:

  • condition is an expression which evaluates to a boolean.
    • If this expression evaluates to true, the code block will be run.
    • Brackets surrounding the condition are optional.
  • ... is the code to run if the condition is true.

Example:

if 2 + 2 == 4 {
    puts "phew!"
}

while

Runs a block of code until the provided condition is false.

Syntax:

while condition {
    ...
}

where:

  • condition is an expression which evaluates to a boolean.
    • If this expression evaluates to false, the code block will not be run anymore.
    • Brackets surrounding the condition are optional.
  • ... is the code to run while the condition is true.

Example:

while true {
    puts "To infinity and beyond!"
}

return

Returns a value from a function.

Syntax:

return value

where value is a value with the same type as the function’s return type.

ground

Inline Ground is potentially dangerous. Only use if you know what you’re doing!

Inserts inline Ground code into the generated program.

Syntax:

ground {
    ...
}

where ... is the Ground code to insert.

See here for details about Ground.

Note: Solstice cannot keep track of state inside ground blocks! Ground will allow you to do things without the overhead of the Solstice type checker.

To extract a value from a Ground block, do something like this:

x = 0
ground {
    set &x 10
}

puts x

so the type checker can know what x is.

use

The use operator lets you import code from libraries, either from in the local folder or installed in the $SOLSTICE_LIBS directory, which defaults to /usr/lib/solstice.

When using use, Solstice will insert the selected file’s contents at that position.

Local use

Supply a string after use which is the path to the file to import, without the .sols extension.

use "parser/Node"
use "parser/parser"

Global use

Supply an identifier after use which is the name of the library to import, without the .sols extension.

use io

Function Definition

Named Functions

Define a named function with the following syntax:

def functionName(args) type {
    ...
}

where:

  • functionName is the name of the function.
    • If functionName is already defined as a function or other value, it will only be overwritten if the type does not change.
  • args is multiple comma-seperated pairs of:
    • a type identifier for the parameter, and
    • an identifier (representing the parameter name)
  • type is the type of value which the function will return
  • ... is the code inside the function (the function body).
    • The function body will have access to previously set variables through a closure. The closure is a copy of all variables in their current state at function definition time.
    • The function body will also have access to the parameters defined in args.

Example:

def add(int a, int b) int {
    return a + b
}

Anonymous/Lambda functions

Define a lambda function with the following syntax:

lambda(args) type {
    ...
}

where:

  • args is multiple comma-seperated pairs of:
    • a type identifier for the parameter, and
    • an identifier (representing the parameter name)
  • type is the type of value which the function will return
  • ... is the code inside the function (the function body).
    • The function body will have access to previously set variables through a closure. The closure is a copy of all variables in their current state at function definition time.
    • The function body will also have access to the parameters defined in args.

Example:

add = lambda(int a, int b) int {
    return a + b
}

Lambda functions are most useful when passed as arguments to other functions.

Struct Definition

Define a struct with the struct keyword.

Syntax:

struct StructName {
    ...
}

where:

  • StructName is the name of your struct
  • ... is the body of your struct

Struct Body

Inside the struct body, you can:

  • Define fields
  • Define methods
  • Define special methods (constructor, destructor, duplicator, as)

Defining fields

A field in a struct is defined in the same way as a variable.

struct MyStruct {
    x = 5
}

This creates a field named x with a default value of 5.

Defining methods

A method in a struct is defined in the same way as a named function.

struct MyStruct {
    def myMethod() int {
        return 0
    }
}

Methods have access to the struct’s members through the self object, which is implicitly passed.

struct MyStruct {

    x = 10

    def myMethod() int {
        return self.x * 2
    }
}

Private and protected fields

A private field is a field which only methods inside the object can read and write.

A protected field is a field which only methods inside the object can write to, however anywhere else in the program the field can be read.

All other fields are public, meaning anywhere in the program can read or write these fields.

Methods and special methods are by default protected, however can be made private.

struct MyStruct {
    private x = 10
    protected y = "Hi"

    private doSomething() int {
        return 14
    }
}

Defining special methods

In Solstice, objects have some special methods which provide ease of use while handling these objects.

Constructor

A constructor is used to initialize an object with user-provided fields.

Define a constructor like this:

struct MyStruct {
    constructor(args) {
        ...
    }
}

where:

  • args is multiple comma-seperated pairs of:
    • a type identifier for the parameter, and
    • an identifier (representing the parameter name)
  • ... is the constructor body
    • The constructor body has access to the self object, which is how it can modify the newly created object.
    • The self object is automatically returned at the end of the constructor, however can be returned manually if required.

Use a constructor like this:

MyStruct(args)

where:

  • args is many comma-seperated expressions corresponding to the signature of the defined constructor

Destructor

A destructor is used to destroy an object once it goes out of scope.

Define a destructor like this:

struct MyStruct {
    destructor {
        ...
    }
}

where:

  • ... is the destructor body
    • The destructor body has access to the self object, which is how it can access and modify the object which is being destroyed.
    • There is no need to return a value from the destructor.

Note how the destructor does not take any arguments.

Duplicator

A duplicator is used to copy an object when it is assigned to a new name, or passed to a function.

Define a duplicator like this:

struct MyStruct {
    duplicator {
        ...
    }
}

where:

  • ... is the duplicator body
    • The destructor body has access to the self and old objects.
      • The self object is the new duplication and will be automatically returned
      • The old object is the old object and will not be copied out

Note how the duplicator does not take any arguments.

As methods

As methods allow easy conversion between different types.

Define an as method like this:

struct MyStruct {
    as type {
        ...
    }
}

where:

  • type is the type which the object will be converted to
  • ... is the as method body
    • The self object is avaliable inside the as method
    • You will need to initialize and return a new value with the specified type

Use an as method like this:

myobj as type

where:

  • myobj is an object with an as method which provides a conversion to type
  • type is the target type

“Vela” 0.x.x

Vela is the codename for the 0.x.x releases of Solstice. It is named after the Vela constellation.

Changes

Vela is the prerelease version of Solstice, and is the phase where core compiler features are added. Here are some features added in Vela to the compiler:

  • puts
  • Variables
  • Values
  • Static type system
  • if, while control flow
  • Functions
    • Lambda/Anonymous Functions
    • Named Functions
    • Closures attached to functions
  • Structs
    • Fields
    • Methods
    • private and protected
    • as-methods
    • Constructors, destructors, duplicators
  • Generics (in progress)
  • pragma directives (in progress)
  • Libraries with use

“Vela” 0.1.0

This is the very first release of Solstice! Not much to see here.

This release contains:

  • puts
  • Variables
  • Values
  • Static type system
  • if, while control flow
  • Functions
    • Lambda/Anonymous Functions
    • Named Functions
    • Closures attached to functions
  • Structs
    • Fields
    • Methods
    • private and protected
    • as-methods
    • Constructors, destructors, duplicators
  • Generics (partially, there are many bugs)
  • pragma directives in the parser
  • Libraries with use

“Fornax” 1.x.x

Fornax will be the codename for the 1.x.x releases of Solstice. It is named after the Fornax constellation.

Release Target

Fornax will release when:

  • The compiler core is stable enough to host moderately sized projects
  • The standard library is capable enough for many programming projects

Fornax is not currently released.