Share your Programming Language Jam submissions here!

← Back to all posts
Arcane Language
h
DLunin (0)

Arcane Language

Arcane is a dynamically typed language with an emphasis on metaprogramming. The main feature is that the code is treated as a first-class citizen: operators and other language constructs work on both values, and on code objects (AST). Also, every value can be transformed into a code that returns it when executed, using the lift operator.

Link to repo
To run a program just put it into main.py, in place of an example program, and hit Run. Then in the output you'll see the lexer tokens, AST tree of your code, and the output of your program.

Features

In Arcane, pretty much everything is an expression, including blocks of code, conditional expressions, function declarations and variable declarations.

Use keyword let to create a variable.

let a = 123
let b = "Hello World"
let c = (123, "Hello, Arcane")
let d = False

Printing

print "Hello World";
let a = 123;
print a

Code block. Consists of several expressions, separated by semicolons. Returns the last value

let a = {
    print "Hello World!";
    let b = 123 + 321;
    b
}

Conditional expressions

if (expression) {
    something()
} else {
    something_else()
}

If expressions return a value, so you can assign the result to a variable:

let y = 5;
let x = if (y < 2) "Hello" else "World"

Functions. Currently only positional arguments are supported.

let dist2 = funciton(x, y) {
    x*x + y*y
};
dist2(3, 4)

Example: factorial function

let factorial = function(x) {
	if (x == 0) {
		1
	} else {
		x * (factorial(x - 1))
	}
};
factorial(5)

Classes.

class Point(x, y) {
    let dist2 = function(x, y) {
        x*x + y*y
    }
};
let p = new Point(1, 2)

Lift. This is the main feature of the language. Using this operator, we can transform any expression into code that returns it. This is how we can construct code objects (ASTs) in our programs.
Let's start off with lifting simple values:

lift 1
Output:
ALiteral(1)
lift "Hello World!"
Output:
ALiteral("Hello World!")

Most operators work on ASTs as well as on ordinary values. When an operator is used on ordinary values, it's result is computed right away -- and if it's used on ASTs it returns an AST of that operator with the passed arguments. Let's see how it works:

(lift 1) + (lift 2)
Output:
BinaryOp(+)
├── lhs: ALiteral(1)
└── rhs: ALiteral(2)
if (lift true) {
	lift 1
} else {
	lift 2
}
Output:
ACondition
├── if: ALiteral(True)
├── then: ALiteral(1)
└── else: ALiteral(2)

ASTs can be executed using the run operator:

run (lift 1 + lift 2)
Output:
3

Roadmap

  1. Finish the interpreter: fix bugs (there's a lot of them, honestly), add all basic variable types and data structures, classes/objects, return statements.
  2. Implement a 'meta-circular stage-parametric' interpreter as in paper, and replicate other interesting from there, using this language as a basis instead of a lisp-like language used there.
  3. Implement translator functions that receive an Arcane AST and return the corresponding Python/Javascript AST
  4. Implement translator functions into a compiled language, most likely C++
  5. Implement (optional) static type checking
Commentshotnewtop
TheDrone7 (1423)

You seem to have mentioned no teammates in your post, please edit the post to include them in the post if there are any. Reply to this comment when you've done so, moving to the share board instead for now.

DLunin (0)

@TheDrone7 For some reason, updating the post doesn't work so here is the team info:
Our team