/Ri

Tiny statically-typed (embeddable) language.

Primary LanguageCMIT LicenseMIT

Ri

Tiny statically-typed (embeddable) language.

Motivation

  • Language to replace Lua where more stable performance and control is needed.
  • Language to replace C with language of similar control, but better possibility of code organization (packages or namespaces).
  • Language that maps APIs and paradigms to the script with zero friction.

Runt

Project is not being made in isolation, it is made as a direct requirement of Runt project. Runt needs this for it's configuration, command customization and extensions.

Inspiration

  • Go -- Love syntax and a feature set of Go (minus garbage collection)
  • WebAssembly -- Love most of the design, VM takes big chunk of notes from this.
  • Quake3 VM -- Love idea of compiling VM to x64 at runtime, VM/x64 takes notes from this.
  • Bitwise's Ion -- Ideas and knowledge stolen with love.

Features

Implementation:

  • Embeddable.
  • STB-style libaries.
  • Minimal binary size.
  • No cstdlib dependency.
  • No LLVM dependency.

Language:

  • Simple Go-inspired syntax.
  • Type inference.
  • No built-in memory management.
  • Packages.
  • Most of what C does.
  • Bring your own library code.
  • Compile time execution.

Organization

Project is planned to be split to STB-style modules:

  • ri.h
    • Library
    • Lexing, Parsing, Resolution, Validation.
    • Take string, output AST or error.
  • ri-to-vm.h
    • Library
    • Take RiAST, output RiVM module blob.
  • ri-vm.h
    • Library
    • Take RiVM blob, run it.

Standalone programs:

  • ri-to-c.c
    • Program
    • Take RiAST, output C file(s).
    • Run compiler.
    • Run executable.

To do

The work is split to phases:

  • Phase 1 AST: Basics (current)
    • Lexer, parser and resolver basics
    • All statements
    • Simple scalar types
    • Draft VM compilation
  • Phase 2 AST: Compound types
    • Enum
    • Pointer
    • Struct
    • Union
    • Initializers
  • Phase 3 AST: Slices
    • C arrays with count
    • Packages
  • Phase 4 VM: Compilation and Execution
    • Compiling to VM
    • Integration with Runt using simple AST interpreter for initializers.
  • Later:
    • Compiling VM to x64
    • Compiling to C

The list will grow as I go.

  • Built-in types
    • int8
    • uint8
    • int16
    • uint16
    • int32
    • uint32
    • int64
    • uint64
    • float32
    • float64
    • bool
    • Complex type(s)
      • complex64
      • complex128
    • SSE type(s)
    • Pointers
      • Function pointers
    • Struct
    • Union
    • Enum
    • Slices
      • []type
  • Constants
    • Untyped constant literal
      • Integer
      • Real
      • Boolean
      • String
      • Initializers
      • Nil
    • Typed named constants
    • Untyped named constants
  • Comments
    • Line comments
    • Block comments
  • Function declaration
    • function <name> (<inputs>) (<outputs>) { ... }
    • function <name> (<inputs>) <type-spec>
    • function <name> (<inputs>)
    • Convenience syntax for function arguments of same type (a, b int32)
  • Function prototype declaration
    • function <name> (<inputs>) (<outputs>)
  • Function type
    • function (<inputs>) (<outputs>)
    • function (<inputs>) <type-spec>
    • function (<inputs>)
  • Call
    • <name>(<arguments>)
    • Type checking.
  • If statement
    • if <pre-st>; <condition> { ... }
    • if <condition> { ... }
    • if ... { ... } else { ... }
    • if ... { ... } else if ...
    • Type checking.
  • For statement
    • for <pre-st>; <condition>; <post-st> { ... }
    • for <pre-st>; ; <post-st> { ... }
    • for <pre-st>; ; { ... }
    • for ; <condition>; { ... }
    • for ; ; { ... }
    • for <condition> { ... }
    • { break }
    • { continue }
    • Type checking.
  • Switch statement
    • switch <pre-st>; <expr> { ... }
    • case <const>:
    • default
    • break or fallthrough?
  • Goto statement
    • goto <label>
    • label:
  • Arithmetic expressions
    • -a
    • +a
    • --a (L, TBD)
    • ++a (L, TBD)
    • a-- (L, TBD)
    • a++ (L, TBD)
    • a + b
    • a - b
    • a * b
    • a / b
    • a % b
    • a = b
    • a += b
    • a -= b
    • a *= b
    • a /= b
  • Bitwise expressions
    • ~n
    • a ^ b
    • a & b
    • a | b
    • a << b
    • a >> b
    • a &= b
    • a |= b
    • a ^= b
  • Comparison expressions
    • a < b
    • a > b
    • a <= b
    • a >= b
    • a == b
    • a != b
  • Boolean expressions
    • !n
    • a && b
    • a || b
  • ASTNode/Type checking

To be determined

Language details to be determined.

  • No semicolons
    • REQUIREMENT: No whitespace significance (cannot be determined by new-line characters).
    • Semicolon after return can be determined by whether function has an output argument.
    • Semicolon after function input arguments where a return type without parens might occur is problematic.
      • func (a int32);? int32;?
      • Make return value to be required (introducing void)?
      • Make return value to be always wrapped in parens? func (a int32) (int32)?
  • Multiple function output arguments
    • In C implemented as non-const pointer parameters.
    • Really wanted only for error reporting.
      • Zero, one or two outputs only?
      • Single output with one additional implicit error output?
  • Prefix and postfix ++ and -- operators as statements or expressions?
    • These are technically x += 1, so assignment which is a statement.
  • Named function output argument(s)
    • Will attempt.
  • Strings
    • []char8, []char16, []char32 slices
    • No zero-termination guarantee.
    • No string + string bullshit.
    • How to deal with zero-terminated strings for C APIs compatibility?
  • Boolean types
    • For now, we're going with what Go does: We're going with 8-bit bool, in order to protect type safety and support explicit casting.
      • int cannot be cast to bool, you need to do i != 0
      • bool cannot be cast to int, you need to do if b { i == 1 }
      • bool is not supported by arithmetic operations.
      • Some of these might change though after proper testing.
        • The cast from bool to int is quite safe.
        • Problem is that some arithmetic operations with bool make sense in order to do branchless calculations.
  • Go interfaces
  • Code in root?
    • Module is function?
    • Module has root code as main function?
    • Pros:
      • Good for scripting.
      • Good for module initialization.
    • Cons:
      • Incompatible with C's #include (initialization has to be called manually)
  • Context as silent argument?