Skip to content

jowi-dev/arcane

Repository files navigation

Arcane Compiler

Based on my infatuation with Elixir and Odin, along with practicalities of JS

TLDR - A hammer so I can see the world as a nail

Syntax Pending

// Everything is a module. This is familiar to Elixir,
// but differs in that there are explicit declarations for
// dependencies, behaviours, macros, and system deps.
Arcane.Users :: module (
  deps: []
  sys: []
  expands: []
  contracts: []
) => {
    // Arrow Syntax from JS
    // Type system for declaring new types
    __MODULE__ :: struct  => {
        name@String: ""  
        email@String: "" 
    }

    // Declaration syntax from Odin/Jai
    searchUser(%{email: String} | %{name: String}) -> __MODULE__ :: args@?(
        // Automatic variable binding: email maps to `email: email`
        (%{email}) => Repo.get_by(email: email)
        (%{name}) => Repo.get_by(name: name)
        _args => Error("Invalid Args")
    )

    getUsers(String) -> __MODULE__ :: (name) => {
    //Using creates a block which automatically cleans after scope close
        using
            arena <- Arena.new(1024 * 1024)
            repo <- Repo.connect()
            file <- File.write("data.txt") => {

            // Arenas are part of the standard library to help create predictable performance
            twenty_four <- Arena.alloc(24 arena)
            // Type declaration after statement
            query@String = String.new("select * from users where name = '#{name}'" arena)

            // implicit type casting
            result <- Repo.query(query repo arena)

            // Nix like matching handles conditionals
            result@(
                Ok(data) => File.write(data file)
                Error(msg) => Error(msg)
            )
        // Arena, Repo, and File would all call dispose() after the scope ends

        // Catch statement familiar to with/else in Elixir
        catch
            error@ConnectError(msg) => Error("failed to connect ${msg}")
            error@WriteError(msg) => Error("failed to write ${msg}")
            error => Error("Unexpected: ${msg}")
        }
    }

    createUser(String String) -> __MODULE__ :: (name email) => {
        __MODULE__.new()
        |> Map.put(:name name)
        |> Map.put(:email email)
        |> ensure_unique() 
        |> @?(
            %User{} = user => Ok(user)
            error => Error(error)
        )
    }

    /**
    * Docs attached to function headers via multi line comments
    */
    getAllNames(^list(User) list(User)) -> String.t() :: args@?(
        // Looping is done via recursion. The compiler is TCO'd so that it performs and behaves the same as loops
        // via jump/jump not equal
        // Head/Tail recursion available
        (users*@[user | rest] out = []) => {
            out = [user.name | out]
            
            getAllNames(rest out)
        }

        // Matching on an empty string, and a list with User types
        (users*@[] out@list(User)) => Arcane.List.reverse(out)
    )
}
flowchart TD
    A[Source Code] --> B[Lexer]
    B --> C[Parser]
    C --> D[AST]
    D --> E[S-expressions]
    
    E --> F[LLVM IR Generator]
    E --> G[Nix Expression Generator]
    
    F --> H[LLVM Backend]
    G --> I[Nix Evaluator]
    
    H --> J[Native Binary]
    I --> K[Nix Store Path]

    note1[Other Backends]
    note2[System configuration]
    note3[Runtime execution]
    
    E -.- note1
    I -.- note2
    J -.- note3
Loading

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/arcane.

About

Arcane is a programming language that makes your work feel like magic

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors