Skip to content

Latest commit

 

History

History
251 lines (176 loc) · 5.78 KB

CHANGELOG.md

File metadata and controls

251 lines (176 loc) · 5.78 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

No unreleased changes yet

[0.0.0-alpha] - 2022-08-20

Added

Changed

Fixed

[0.0.1-alpha] - 2023-06-14

Added

Added stable LIR frontend with type checker and polymorphic types.

Changed

Expanded standard instruction set.

Fixed

[0.0.2-alpha] - 2023-12-20

Added

Added methods to types, associated constants, and expanded support for foreign functions.

Changed

Changed type system to accommodate methods.

Fixed

[0.0.3-alpha] - 2023-12-27

Added

Changed

Fixed

Fixed bug where unary - operator did not type-check on Float values.

[0.0.4-alpha] - 2024-3-22

Added

Support for typechecking expressions in parallel. Support for SIMD vector instructions.

Changed

All the VM instructions now take an optional "size" constant parameter which determines the size of the vector they're operating on. The register is now a vector, not a scalar.

Removed sage-os and x86 targets. x86 will be added back later, but likely using the C target as an intermediate step to produced better optimized x86.

New VM instructions:

  • Inc
  • Dec
  • Offset
  • And
  • Or
  • Not
  • BitwiseAnd
  • BitwiseOr
  • BitwiseXor
  • BitwiseNot

Fixed

Generated code size is now up to 7x smaller than before.

[0.1.0-alpha] - 2024-9-4

Sage has just gotten a major upgrade, with a new module system📦 parser📝 and the Sage Lisp Preprocessor🛸!!!

Added

// Define some code that modifies the AST of the expression it's called on
#![(defun square_sage_const(x) {
    // Get a constant integer
    (define n x@"ConstExpr"@"Int")
    // Return the constant integer squared
    ["ConstExpr" ["Float" n * n]]
})]

// Call the compile time macro on 5.
// This will cause the compiler to perceive this code as `println(25)`
println(#[square_sage_const] 5);
  • Module system
// Import a module from a file named `from_file.sg`
mod from_file;

// Define a module `io` with `getchar`
mod io {
    fun getchar(): Char {
        let mut ch = '\0';
        input(&mut ch);
        return ch;
    }
}

// A module to test importing from other modules
mod testing {
    mod internals {
        // Import getchar from two modules up
        from io import getchar;
        
        // Use it in a function
        fun get_two(): (Char, Char) { (getchar(), getchar()) }
    }

    // Get two chars and print them
    fun get_two_then_print() {
        // Import from a submodule, which imports from a supermodule
        from internals import get_two;
        let (a, b) = get_two();
        print(a, b);
    }
}

from testing import get_two_then_print;
get_two_then_print();

// Get two values and print them
for let mut i=0; i<6; i+=1; {
    // We can also use the full path name
 	testing.get_two_then_print();
}
  • Standard library
from std.fallible import Option, Result;

enum Error {
    DivideByZero { numerator: Int },
    Custom(&Char)
}

fun divide(n: Int, d: Int): Option<Int> {
    match d {
        0 => Option<Int> of Nothing,
        _ => Option<Int> of Some(n / d)
    }
}


fun main(): Result<(), Error> {
    println(divide(5, 2));
    println(divide(5, 0));

    return Result<(), Error> of Ok(());
}

println(main());
  • Better constant evaluation
  • from module.submodule import x, y as alias_for_y; import statements
  • from module.submodule import * import statements

Changed

  • The def keyword has been changed in favor of fun.
  • for loops now have an extra semicolon on the last statement. i += 1 { becomes i += 1; {.

Fixed

The compiler is significantly faster -- about 20 times faster at compiling the AES example. This is mainly due to the much faster parser implemented with Nom instead of Pest. There are also several optimizations with constant evaluation I added, along with optimizations for how declarations are typechecked.

[0.1.1-alpha] - 2024-9-8

Added

Added const generics, so constant parameters can be passed along with types through templates. This allows the typechecker to be applied to many more aspects of code, including examples like typechecking dimensions of matrix multiplications at compile time.

struct Matrix<T, const Rows: Int, const Cols: Int> {
    arr: [[T * Cols] * Rows]
}

impl Matrix<T, Rows, Cols> {
    fun new(x: T): Matrix<T, Rows, Cols> {
        return {arr=[[x] * Cols] * Rows};
    }

    fun get(&self, row: Int, col: Int): &T {
        return &self.arr[row][col];
    }

    fun mul<const NewCols: Int>(
        &self,
        other: &Matrix<T, Cols, NewCols>,
        zero: T,
        add: fun(T, T) -> T,
        mul: fun(T, T) -> T
    ): Matrix<T, Rows, NewCols> {
        let mut result = Matrix.new<T, Rows, NewCols>(zero);
        for let mut j=0; j<NewCols; j+=1; {
            for let mut i=0; i<Rows; i+=1; {
                let mut sum = zero;
                for let mut k=0; k<Cols; k+=1; {
                    sum = add(sum, mul(self.arr[i][k], other.arr[k][j]));
                }
                result.arr[i][j] = sum;
            }
        }
        result
    }
}

let mut x = Matrix.new<Int, 4, 4>(10);
let mut y = Matrix.new<Int, 4, 4>(5);

println(x);
println(y);

fun add_ints(a: Int, b: Int): Int = a + b;
fun mul_ints(a: Int, b: Int): Int = a * b;

let z = y.mul<4>(&x, 0, add_ints, mul_ints);
println(z);

Changed

Changed type system to accommodate const generics. This was done by adding a ConstParam variant to types.

Fixed

Improved parser speed by a significant amount during the process.