-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from sigmasoldi3r/main
Nightly release test
- Loading branch information
Showing
12 changed files
with
727 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Build artifacts | ||
|
||
on: | ||
push: | ||
branches: [ "nightly", "release" ] | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
jobs: | ||
build_matrix: | ||
strategy: | ||
matrix: | ||
os: [ubuntu-latest, windows-latest, macos-latest] | ||
profile: [dev, release] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Build artifacts | ||
run: cargo build --profile ${{ matrix.profile }} --verbose | ||
- name: Upload a Build Artifact | ||
uses: actions/upload-artifact@v3.1.2 | ||
with: | ||
path: target/debug/saturnus |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Test | ||
|
||
on: | ||
pull_request: | ||
branches: [ "main", "release", "nightly" ] | ||
push: | ||
branches: [ "main", "nightly" ] | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Run tests | ||
run: cargo test --verbose |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
[package] | ||
name = "mantra" | ||
name = "saturnus" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Saturnus | ||
|
||
**Saturnus** is a programming language that aims to have a simplified mix of | ||
[Rust programming language](https://www.rust-lang.org/) and [Lua](https://www.lua.org/). | ||
|
||
The main target for Saturnus compiler is **Lua**, but multi-target compilation | ||
will arrive in the future, so stay tuned if you like the language. | ||
|
||
The original purpose of this language was to provide an easy-to-learn syntax, | ||
and fast compilation times, to replace Lua scripts currently. | ||
|
||
## Why replace Lua? | ||
|
||
I like many aspects of Lua, specially how fast and lightweight the VM is. But | ||
original Lua syntax is nowadays a little bit old, and it needs some rework to | ||
make the scripts less verbose and more easy to write. | ||
|
||
Among other things, here are some key aspects that Saturnus changes: | ||
|
||
- Function syntax is simpler, `fn` instead of `local function`. | ||
- Lambdas are simpler yet familiar, Eg: `fn() 1 + 2 end`. | ||
- More idiomatic class definitions: `class MyClass end` instead of [the classic one](https://www.lua.org/manual/2.4/node36.html). | ||
- Decorators! | ||
- A built-in prelude library for runtime type checks. | ||
- Nice string interpolation. | ||
- Terser loops. | ||
- Built-in operator overloading. | ||
- Custom operators. | ||
- Some [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) (Which enables reflection). | ||
|
||
## Some examples | ||
|
||
Some little examples: | ||
|
||
```rs | ||
use println from "prelude"; | ||
use rti.Typed from "prelude"; | ||
|
||
class Greeter | ||
let who; | ||
|
||
// This will make the function panic if "who" is not a string! | ||
@Typed([rti.String]) | ||
fn new(who) | ||
Greeter { who } | ||
end | ||
|
||
fn greet(self) | ||
return "Hello {self.who}!"; | ||
end | ||
end | ||
|
||
// The classic OOP hello world: | ||
let greeter = Greeter::new("Saturnus"); | ||
println(greeter.greet()); | ||
``` |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
use std::f32::consts::E; | ||
|
||
use crate::parser::{ | ||
Assignment, BinaryExpression, CallExpression, Class, Declaration, DotExpression, Expression, | ||
Function, Lambda, Number, Return, Script, Tuple, UnaryExpression, | ||
}; | ||
|
||
#[derive(Debug)] | ||
pub struct VisitError; | ||
|
||
pub trait Visitor<T> { | ||
// Those need to be implemented explicitly by the user: | ||
fn visit_return(&self, context: T, stmt: &Return) -> Result<T, VisitError>; | ||
fn visit_class(&self, context: T, stmt: &Class) -> Result<T, VisitError>; | ||
fn visit_fn(&self, context: T, stmt: &Function) -> Result<T, VisitError>; | ||
fn visit_assignment(&self, context: T, stmt: &Assignment) -> Result<T, VisitError>; | ||
fn visit_declaration(&self, context: T, stmt: &Declaration) -> Result<T, VisitError>; | ||
fn visit_expression_statement(&self, context: T, stmt: &Expression) -> Result<T, VisitError>; | ||
fn visit_lambda(&self, context: T, expr: &Lambda) -> Result<T, VisitError>; | ||
fn visit_reference(&self, context: T, expr: &DotExpression) -> Result<T, VisitError>; | ||
fn visit_call(&self, context: T, expr: &CallExpression) -> Result<T, VisitError>; | ||
fn visit_tuple(&self, context: T, expr: &Tuple) -> Result<T, VisitError>; | ||
fn visit_number(&self, context: T, expr: &Number) -> Result<T, VisitError>; | ||
fn visit_string(&self, context: T, expr: &String) -> Result<T, VisitError>; | ||
fn visit_unit(&self, context: T) -> Result<T, VisitError>; | ||
fn visit_binary(&self, context: T, expr: &BinaryExpression) -> Result<T, VisitError>; | ||
fn visit_unary(&self, context: T, expr: &UnaryExpression) -> Result<T, VisitError>; | ||
|
||
// Generically implementable matching patterns: | ||
fn visit_expression(&self, context: T, expression: &Expression) -> Result<T, VisitError> { | ||
match expression { | ||
Expression::Lambda(e) => self.visit_lambda(context, e), | ||
Expression::Reference(e) => self.visit_reference(context, e), | ||
Expression::Call(e) => self.visit_call(context, e), | ||
Expression::Tuple(e) => self.visit_tuple(context, e), | ||
Expression::Number(e) => self.visit_number(context, e), | ||
Expression::String(e) => self.visit_string(context, e), | ||
Expression::Unit => self.visit_unit(context), | ||
Expression::Binary(e) => self.visit_binary(context, e), | ||
Expression::Unary(e) => self.visit_unary(context, e), | ||
} | ||
} | ||
fn visit_script(&self, context: T, script: &Script) -> Result<T, VisitError> { | ||
script | ||
.statements | ||
.iter() | ||
.fold(Ok(context), |context, stmt| match stmt { | ||
crate::parser::Statement::If => todo!(), | ||
crate::parser::Statement::For => todo!(), | ||
crate::parser::Statement::Loop => todo!(), | ||
crate::parser::Statement::While => todo!(), | ||
crate::parser::Statement::Return(e) => self.visit_return(context?, e), | ||
crate::parser::Statement::Class(e) => self.visit_class(context?, e), | ||
crate::parser::Statement::Function(e) => self.visit_fn(context?, e), | ||
crate::parser::Statement::Assignment(e) => self.visit_assignment(context?, e), | ||
crate::parser::Statement::Declaration(e) => self.visit_declaration(context?, e), | ||
crate::parser::Statement::Match => todo!(), | ||
crate::parser::Statement::Expression(e) => { | ||
self.visit_expression_statement(context?, e) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
pub struct UnevenIndentationError; | ||
impl std::fmt::Debug for UnevenIndentationError { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.debug_struct("Uneven Indentation: Attempting to pop furhter than 0!") | ||
.finish() | ||
} | ||
} | ||
|
||
/// # String code builder | ||
/// | ||
/// This simple immutable builder accounts for raw strings (So it is agnostic | ||
/// from the targetted output), but retains indentation aspects. | ||
/// | ||
/// This means that you have an indentation stack, with it's state retained | ||
/// between calls, without having to store it in your code emitter. | ||
/// | ||
/// Each call, consumes the builder and returns an extended version of it. | ||
/// If you want to preserve the state, clone the structure by calling `.clone()` | ||
/// explicitly. | ||
/// | ||
/// Example: | ||
/// ```rs | ||
/// let out = Builder::new(" ") | ||
/// .put("hello") | ||
/// .push().line() | ||
/// .put("my") | ||
/// .pop().unwrap().line() | ||
/// .put("world!") | ||
/// .collect() | ||
/// ``` | ||
/// Yields: | ||
/// ``` | ||
/// hello | ||
/// my | ||
/// world | ||
/// ``` | ||
#[derive(Clone)] | ||
pub struct Builder { | ||
level: u16, | ||
indent: String, | ||
buffer: String, | ||
} | ||
impl Builder { | ||
pub fn new<T>(indent: T) -> Self | ||
where | ||
T: Into<String>, | ||
{ | ||
Builder { | ||
level: 0, | ||
indent: indent.into(), | ||
buffer: Default::default(), | ||
} | ||
} | ||
pub fn collect(self) -> String { | ||
self.buffer | ||
} | ||
pub fn push(self) -> Self { | ||
Builder { | ||
level: self.level + 1, | ||
..self | ||
} | ||
} | ||
pub fn pop(self) -> Result<Self, UnevenIndentationError> { | ||
if self.level == 0 { | ||
Err(UnevenIndentationError) | ||
} else { | ||
Ok(Builder { | ||
level: self.level - 1, | ||
..self | ||
}) | ||
} | ||
} | ||
pub fn put<T>(self, fragment: T) -> Self | ||
where | ||
T: Into<String>, | ||
{ | ||
Builder { | ||
buffer: format!("{}{}", self.buffer, fragment.into()), | ||
..self | ||
} | ||
} | ||
pub fn line(self) -> Self { | ||
Builder { | ||
buffer: format!("{}\n{}", self.buffer, self.indent.repeat(self.level.into())), | ||
..self | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.