luxya
luxya copied to clipboard
Programming language with a tree-walking interpreter written in Rust©™.
luxya ✨
Luxya is a Lox-based programming language with a tree-walking interpreter written in Rust©™.
To download precompiled binaries for GNU/Linux and Windows visit the releases page!
-
Lox-luxya differences
- Additions
- Syntax
- Backend
- Native functions
- Usage
- Examples
- Compilation and development
Lox-luxya differences
Additions:
- lists!; read more
- square bracket accessor (
[expression]
); read more - grouping accessor (
.(expression)
); read more - full object notation; read more
- chars; read more
- the modulo (
%
) operator
Syntax differences:
- function declarations are expressions, rather than statements, so you can create anonymous (but not strictly) functions you want to use in-place:
function_name(10, a, fun () { print "callback" })
- introduced
let
instead ofvar
, andconst
for immutable declarations -
if
's,else
's, andfor
's body has to be a block -
if
s condition doesn't need to be a grouping (basically you can do:if true { ... }
) - although there is no type coercion, any value that's not strictly
true
will be treated asnot true
when placed inif
's orfor
's condition -
for
's initialization consists of three, not grouped fields (e.g.:for let i = 0; i < 10; i = i + 1 { ... }
) - there are no
while
loops, but you can achieve the same behaviour withfor
(while true { ... }
is the same asfor ; true; { ... }
) - you can state an infinite loop by omitting every field:
for ;; {}
-
init
(Lox's constructor method) is namedconstructor
- you cannot call an instance's
constructor
directly (constructor
s are only callable by usingClassname()
orsuper()
) - to call a superclass's constructor you need to call the
super
keyword, as you would a function - inheritance is done with the
extends
keyword, replacing the<
syntax - chars, which you can read more about here
Backend differences:
- numbers are
IEEE 754-2008
compliant (rust's f64 underneath) - no type coercion, no truthy nor falsy values
- no visitor pattern
- reference counting because there's no garbage collector to leverage
- shadowing of named values is permitted
Native functions:
You can find full list of native functions here
Usage
To run any script source run:
$ luxya <source>
To run in REPL mode (which is not yet finished):
$ luxya
Examples
for let i = 0; i < 10; i = i + 1 {
print i;
}
fun shout(text) {
print text + "!";
}
shout("hi");
class Language {
constructor(name) {
this.name = name;
}
say_language() {
print this.name;
}
}
class Luxya extends Language {
constructor() {
super("luxya");
}
say_language() {
print "✨✨✨";
super.say_language();
print "✨✨✨";
}
}
const luxya = Luxya();
luxya.say_language();
Compilation and development
The source comprises two parts:
- the
src/ast/*
generated bytools/generate_ast.py
- the rest
To get a release build you can use just
:
$ just
Or use cargo:
$ cargo build --release --verbose
There are also a couple of useful dev commands like:
# run REPL in watch mode
$ just watch
# run the `sample_program.lux` in watch mode
# (script source overridable with sample_program_path in justfile)
$ just watch_sample
# run the `generate_ast.py` script with mypy checks in watch mode
# (script source overridable with generate_ast_path in justfile)
$ just watch_generate_ast