Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: The Sage Programming Language (github.com/adam-mcdaniel)
114 points by adamthekiwi99 12 months ago | hide | past | favorite | 28 comments
Sage is a Rust-like programming language built on a brainfuck-inspired VM with LLVM-like properties. https://github.com/adam-mcdaniel/sage

Check out the web-demo to run the compiler in the browser, along with a graphical example using JavaScript interop! https://adam-mcdaniel.net/sage

Sage is designed to be portable, but also useful. To prove its usefulness, I used it to implement a user-space for a new operating system: SageOS https://github.com/adam-mcdaniel/sage-os The language also runs on embedded devices, like the flipper zero!




Sage is a programming language with a low level virtual machine based on a Turing tape. The sage virtual machine has a read/write head and a single register. The read/write head moves around the tape, and uses the register as an accumulator. All worldly input is done through a single instruction, and all worldly output is done through a single instruction. Functionality which cannot be achieved with any algorithm, such as using an operating system’s system calls to write to persistent memory, is also done through two instructions: one for sending values to the virtual machine’s foreign function interface, and one for receiving. The goal of the virtual machine is to allow algorithms to be expressed in the same time complexity as they would on x86, but with the smallest possible number of instructions. This allows sage code to be maximally portable: sage’s core instruction set could be implemented in hardware much easier than any modern architecture due to its very small pool of opcodes and their simplicity

This is an interesting snippet from your website, did this project intentionally start out as an attempt to design around a Turing machine? Or is it just safe to say that all languages executing on a stack with no heap are Turing machines?


Thanks for the great question, and for checking out the project! This project started out because I noticed some really interesting properties about compiling brainfuck-like programming languages while writing high level language compilers that targeted these brainfuck-like backends.

This is the work that inspired Sage: Harbor (https://github.com/adam-mcdaniel/harbor). My goal with Sage was to take everything that makes a brainfuck-like programming language easy to compile, while also keeping all the time complexity and optimizations of regular algorithms. So, in that sense, it started out as an attempt to design around a Turing machine -- I wanted this to be a dialect of brainfuck. The VM doesn't use any stack operations, just operations on a tape pointer + an accumulator!


One thing I like is exploring the structural typing.

However I am confused if the enum's are structural or nominal. It seems necessary to state which enum a variant comes from, like `Direction of South` (for that matter it seems the same is true when constructing structs?). Can you cast enum values to a wider enum type? Or combine different enum values (e.g. through branching - the return of `match`) to construct a value of a wider enum?


Hello, thanks for the great question! Yes, you do have to specify where a variant comes from, but it doesn't have to be nominal at all! Here's an example:

``` enum Option<T> {Some(T), Nothing}

// Create a value with an inline type that doesn't use the nominal `Option`

let opt1 = enum {Some(Int), Nothing} of Some(5);

// Define a second option value, which is assigned with the first

let opt2: Option<Int> = opt1;

// Print the result

println(opt2); ```

You can create a variant of an inline `enum` type, and then typecheck it against another structurally equal type if you so choose!

I hope this example properly illustrates how powerful the structural type-checking is with enums!


That's an interesting approach. So the variant name itself doesn't bear the type information but should be uniquely resolved in the type check time, right? It will be pretty much optimal unless you are doing metaprogramming stuffs.


That's right! I think it's a good balance between giving the typechecker the info it needs, but also being flexible in how you can supply it!


I once pondered about a related generalization: an explicit ellipsis in the identifier. For example `*foo` will match any suitable identifier that ends with `foo`, and it should be uniquely resolved at the end. More ergonomic syntax would use a separator to imply wildcards: for example, an identifier should be a sequence of words separated by `-`, so that `-foo`, `foo-` and `-foo-` really mean `*-foo`, `foo-*` and `*-foo-*` respectively. This can be used to implement a simpler form of module paths.


Fascinating.

I'm imagining you're going to want a kick-ass IDE/linter/VSCode plugin to handle the case when you create a new variable that matches an existing pattern, and automatically making existing references more precise.

Though it might be easier to go the other way - at the presentation layer, automatically shorten variables to the least specific yet unique suffix or something.


Oh that's cool, and makes sense. Is it possible to perform type widening on enums? Or must they match precisely? For example, what happens if I attempt the below?

``` enum Option<T> {Some(T), Nothing};

let opt1 = enum {Some(Int)} of Some(5);

let opt2: Option<Int> = opt1; ```


The struct composition example with Position + Size is really interesting. I can’t say I’ve seen something that works that way before.


Thanks so much! I originally added it to experiment with the structural typing -- the type system is a really cool foundation for some awesome future stuff!

Thanks for checking out the project, I'm glad I was able to surprise you haha! :)


May I suggest replacing the screenshots of code in your readme with just the code?

I mean, it's hard to tell but it basically looks exactly like Rust but without lifetimes/borrow checks.


Hello, yes, I'll go back and add some text examples as well. (I didn't like how GitHub does syntax highlighting though :/)

I put all the example programs in text on the web-demo, though, if you want to see more there! You can copy, read, or modify them there!

https://adam-mcdaniel.net/sage

It's different from Rust in that it has structural typing and a more Python-like experience! Types are constants, and can be printed with `print` like other values

Thanks for your input! I hope you like the project!


FYI, Sage is also the name of a mathematical programming language: https://www.sagemath.org/


Thank you!! Sage will eventually change its name (I just recently found out about this), but I haven't had time to come up with a good replacement name and make art + quippy sayings for it yet! :)

I might just go with a completely made up word to avoid any trademarks entirely haha


What are the constraints that you want for the name?

I was thinking "Pragmata", or something along those lines.

Continuing with natureish themes: Alga Moss Myco Wisp Ivy


My major constraint is just that the name must lend itself well to artistic representations and fun mottos/slogans hahaha!

I love these suggestions, especially Moss and Ivy! Thank you!


I was surprised to find no associated programming languages for sumac and bay (leaf).


Mint? ;)



Hahaha I doubt there's an English word left!!!


Rosemary and Oregano are free! Thyme is not.


How long until we enumerate all the herbs?!?!?!?!?! The pantry's almost empty!!!


I like it! And if that's trademarked too I could always fall back on "spearmint" instead haha


I used SageMath for my masters. It was a life saver.


I'll have to check it out and reimplement it's good features for THIS Sage hahaha


Super cool! How is memory managed? Does it do lifetimes like Rust as well?


Right now, memory is managed like C or C++, but I intend to implement lifetimes in the frontend eventually.

But definitely no garbage collection (although, a target could implement it against the standard and it would work)

Thanks for checking out the project!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: