2 unstable releases

0.10.0 Nov 28, 2024
0.9.2 Aug 18, 2024

#169 in Programming languages

Download history 32/week @ 2024-08-19 2/week @ 2024-08-26 18/week @ 2024-09-16 14/week @ 2024-09-23 18/week @ 2024-09-30 146/week @ 2024-11-25 85/week @ 2024-12-02

231 downloads per month

MIT and LGPL-3.0-only

1MB
21K SLoC

Rust codecov Webpage VSCode Extension Crates.io Version

What is Ryna?

Ryna is an imperative concept programming language with a stong type system. Many of its ideas come from the ULAN Language (Spanish only), of which I'm also the author. The points of this language are to challenge the idea of classical software mantainability and to take extensible programming to an extreme in order to minimize syntatical and semantical noise.

Take a look at the official page to learn about the language and its features!

Can I use Ryna?

Of course! The language is at an experimental stage, so it is indeed usable, but expect some things to fail. You can take a look here for instructions on how to install the interpreter.

Features

These are some of the things you can do with Ryna:

  • Arbitrary precision integer arithmetic.

  • Full parametric algebraic types:

    Int | String;        // Either a number or a string
    (Int, String);       // A number followed by a string
    Array<Int | String>; // An array of elements that are either numbers of strings
    
  • Recursive types:

    class Nil {}
    type Tree<T> = Nil | ('T, Tree<'T>, Tree<'T>);
    
    let t: Tree<Int> = (
        3, 
        (
            1, 
            Nil(), 
            (
                3, 
                (1, Nil(), Nil()), 
                (2, Nil(), Nil())
            )
        ), 
        (2, Nil(), Nil())
    );
    
  • Powerful function overloading semantics: you will be able to define functions using this rich type system and make use of call polymorphism semantics:

    fn this_is_a_test(a: Int) -> Bool {
        return true;
    }
    
    fn this_is_a_test(a: String) -> Bool {
        return false;
    }
    
    // Both valid
    this_is_a_test(5);      // Returns true
    this_is_a_test("Test"); // Returns false
    
  • Generic template-based programming: parametric types are also supported by means of templating in a similar way as C++ does:

    fn<T> is_number(a: 'T) -> Bool {
        return a.is<Int>();
    }
    
    // Template arguments are automatically inferred from the parameters if possible
    5.is_number();        // This is true
    "Test".is_number();   // This is false
    5.is_number<Int>();   // You can also explicitly instantiate the template
    
  • Custom literals: you will be able to create new literals using an internal language called RDL (Ryna Definition Language):

    class Dice {
        // Syntax definition
        syntax from Arg(1{d}, rolls) 'D' Arg(1{d}, faces)
    
        faces: Int
        rolls: Int
    }
    
    //Usage
    dice = 4D20; // Four dice of twenty sides
    
  • Compile-time syntax extensions: you will be able to extend the syntax of the language using RDL by means of high level patterns:

    syntax array_initialization from "<" Arg(<type>, type) ">[" [{Arg(<expr>, elems) "," [s]} Arg(<expr>, elems)] "]" {
        let res = arr<$type>();
    
        @elems.i {
            res.push($elems.i);
        }
        
        return move(res);
    }
    
    let array = <Int>[1, 2, 3, 4];
    
  • Operator and operation definitions: the language allows the definition of new operators and operations using an easy syntax:

    // Operator definition
    unary postfix op "++" (500);
    binary op "<=>" (1000);
    nary op from "`" to "´" (1500);
    
    // Operation definition for each operator
    // These can be overloaded and templated just the same as functions
    op (a: &Int) ++ -> Int {
        return a + 1;
    }
    
    op (a: &Int) <=> (b: &Int) -> Int {
        if a < b {
            return -1;
        }
        
        if a > b {
            return 1;
        }
      
        return 0;
    }
    
    op (a: &Int) `(b: &Int, c: &Int)´ -> Int {
        return a + b * c;
    }
    
  • Built-in testing framework: you can use the @test annotation to build unit tests without external libraries:

    @test
    fn fill_test() -> Bool {
        let res = arr_with_capacity<Int>(3);
        res.fill(100);
    
        for i in res {
            if i != 100 {
                return false;
            }
        }
    
        return true;
    }
    
  • Built-in documentation generator: you can use the @doc annotation document your project and the ryna docs command to generate human-readable markdown files with the documentation of your project:

    @doc(
        "Fills every available position in an array with a given value. The filling starts in the current `len`.",
        array: "the array to fill.",
        value: "the value to fill the available positions with.",
        "An array where every position starting from the previous `len` is `value`"
    )
    fn<T> fill(array: @Array<'T>, value: 'T) -> @Array<'T> {
        while array.capacity() > array.len() {
            array.push(*value);
        }
    
        return array;
    }
    

Projects written in Ryna

If you want to showcase a project here, you can submit a pull request or open an issue :)

RyChess engine

RyChess is a simple chess engine written in Ryna in order to show how the language can be used in medium sized projects. Also, it is used internally as a benchmark when measuring optimizations.

RyGenes

RyGenes is a genetic algorithms library written in Ryna. It allows creating custom crossover and mutation functions and includes examples such as the N-Queens problem.

Rynd

Rynd is a multidimensional array library with native bindings provided by the great ndarray Rust crate.

Contribute

You can contribute to the project by opening issues when you find a bug in the interpreter or when you happen to have a suggestion on how to improve either the language or the documentation. All contributions, big or small, are welcome :)

Dependencies

~52MB
~894K SLoC