🌳 A tiny language interpreter implemented purely in TypeScript's type-system
A tiny language interpreter implemented purely in TypeScript's type-system
This is an extremely simplified language interpreter implemented purely in TypeScript type annotations. You pass your code as a string and get back the result by hovering with your mouse on the resulting type annotation.
The syntax is Lisp-like. If you're not familiar with it, here's a quick comparison to JavaScript's syntax:
LISP JavaScript(add 1 2) add(1, 2) (subtract 5 2) subtract(5, 2) (add 3 (subtract 2 1)) add(3, subtract(2, 1))
The language supports booleans, numbers, strings, conditionals (if statements), and calling the following built-in functions:
++: Increases a number by one.
--: Decreases a number by one.
Eq: Checks if both of its arguments are equal.
And: Returns
trueif both of its arguments are
true.
Or: Returns
trueif at least one of its arguments are
true.
Join: Concatenates two strings together.
It also supports declaring variables and functions (See bellow).
Install
typelangwith
npm install typelangor with
yarn install typelang(requires TypeScript v4.1.0 or above).
The language has support for nulls (no value), numbers, strings, and booleans.
import { Eval } from "typelang";type Result = Eval; // null type Result = Eval; // '123' type Result = Eval; // 'hello' type Result = Eval; // true type Result = Eval; // false
If statements are in the form of:
(If predicate then-expression else-expression)
import { Eval } from "typelang";type Result = Eval; // 'yes' type Result = Eval; // 'no'
The language supports a few built-in functions (listed above) and you can also define custom functions.
Here's how you call a function:
(function-name arg1 arg2 arg3 ...)
import { Eval } from "typelang";type Result = Eval; // 'abcd'
type Result = Eval; // true type Result = Eval; // false
type Result = Eval; // true type Result = Eval; // false
type Result = Eval; // true type Result = Eval; // true
type Result = Eval; // '3' type Result = Eval; // '4'
Declare a variable to hold a value and reference it later on. Here's how you do it:
(Def variable-name value)
Notice that the language returns the last expression, so the first example declares a variable and then returns it:
import { Eval } from "typelang";type Result = Eval; // '1' type Result = Eval; // null type Result = Eval; // '3' type Result = Eval; // 'result: 5'
To declare a custom function, use the following syntax:
(Fun function-name (arg1 arg2) (function-body))
Note that you can access
arg1and
arg2only from inside the function body and not from outside. You can still access variables declared on the global scope from inside the function scope.
import { Eval } from "typelang";type Result = Eval; // 'Hello John Doe'
Notice that all expressions are evaluated but only the last one is returned:
import { Eval } from "typelang";type Result = Eval; // '3' type Result = Eval; // false
never
In case of an error,
Evalreturns
never:
import { Eval } from "typelang";type Result = Eval; // never type Result = Eval; // never type Result = Eval; // never
Note: TypeScript has a limitation on how deep its computation can get. Because of this, we're limited to small inputs. If you're getting the following error:
Type instantiation is excessively deep and possibly infinite, please try using a smaller input.