npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tsukiroku/tiny

v0.3.7

Published

Tiny interpreter

Readme

Introduce

Start REPL

# Install dependencies
npm i

# REPL
npm run start:repl

# You can also from a file.
npm run start:repl [file]

REPL commands

//command ...args

| Command | Description | | ------- | -------------------------------------------------- | | exit | Exit the repl | | mode | Change the mode (repl, lexer, parser, env) |

Web Playground

README | Playground

Interpreter

Tokens

| Token | Identifier | Token | Identifier | | ----------- | ---------- | -------------- | ---------- | | EOF | EOF | ILLEGAL | ILLEGAL | | NUMBER | NUMBER | IDENT | IDENT | | TRUE | TRUE | STRING | STRING | | FUNCTION | FUNCTION | FALSE | FALSE | | ASSIGN | = | COMMENT | COMMENT | | MINUS | - | PLUS | + | | ASTERISK | * | BANG | ! | | PERCENT | % | SLASH | / | | GT | > | LT | < | | NOT_EQUAL | != | EQUAL | == | | COLON | : | COMMA | , | | LPAREN | ( | SEMICOLON | ; | | LBRACE | { | RPAREN | ) | | LBRACKET | [ | RBRACE | } | | LET | LET | RBRACKET | ] | | ELSE | ELSE | IF | IF | | WHILE | WHILE | RETURN | RETURN | | QUOTE | " | SINGLE_QUOTE | ' |

Expressions

Except for If, Function Expression, all expressions must be preceded by a semicolon (;);

| Expression | Syntax | Expression | Syntax | | ---------- | --------------------------------- | ---------- | ---------------------------- | | Literal | | Block | { [expr] } | | If | if (expr) [block] else [block]; | Function | func [name?](args) [block] | | Call | ident(args) | Ident | | | Array | [expr, expr, ...] | Index | ident[number] | | Object | { string: expr, ... } | Assign | [ident / index] = expr |

Statements

| Statement | Syntax | Statement | Syntax | | --------- | ------------------- | --------- | ----------------------- | | Let | let ident = expr; | While | while (expr) [block]; | | Return | return expr; | Block | { statement } |

Priority

1 < ... < 10

| Priority Number | Operator | | --------------- | ------------------------------------------------------ | | 10 | Nullish (??), Element (<-, .), Index ([]) | | 9 | Function Call | | 8 | typeof, delete, throw, use, Prefix (!, -, +) | | 7 | Multiplication (*, /, %) | | 6 | Addition (+, -) | | 5 | Comparison (>, <, >=, <=, in) | | 4 | Equality (==, !=) | | 3 | Logical (&&, ||) | | 2 | Assignment (=) | | 1 | ... |

Operators

| Operator | Syntax | Literal Type | | -------- | ------------ | --------------------------------------------------------- | | + | ... + ... | number, array, string, object | | - | ... - ... | number | | * | ... * ... | number | | / | ... / ... | number | | % | ... % ... | number | | == | ... == ... | number, string, boolean, array, object | | != | ... != ... | number, string, boolean, array, object | | < | ... < ... | number | | > | ... > ... | number | | <= | ... <= ... | number | | >= | ... >= ... | number | | <- | ... <- ... | array, object, Any | | . | extends <- | extends <- | | ?? | ... ?? ... | Any | | in | ... in ... | string, number, object, string, number, object, array |

Literal

| Type | Syntax | | --------- | -------------------------------------------- | | string | "String", 'String' | | number | [-?]Number.[Number?] | | boolean | true, false | | dict | { [key (String, Number)]: [value (Any)], } | | array | [value (Any)] | | func | func [name?]([args]) [block] |

Built-in functions

| Function | Arguments | | ------------------ | --------- | | import | string | | eval | string | | js | string | | to_s | Any | | to_n | Any | | to_b | Any | | to_a | Any | | options | | | regExp | |

Standard library

  • @std/
    • lib
    • io
      • print(args*) -> NULL
      • println(args*) -> NULL
    • array
      • push(array, value) -> array
      • pop(array) -> array
      • shift(array) -> array
      • unshift(array, value) -> array
      • slice(array, start, end) -> array
      • join(array, separator) -> string
      • forEach(array, callback) -> NULL
        • callback(value, index)
      • repeat(value, count) -> array, repeat(count) -> array
      • reduce(array, callback, initial) -> Any
        • callback(previous, current)
      • map(array, callback) -> array
        • callback(value, index)
    • util
      • funcTools -> object
      • length(array) -> number
      • match(value, [pattern], default) -> Any
      • ternary(condition, trueValue, falseValue) -> Any
    • [string]
      • split(string, separator) -> array
      • concat(args*) -> string
      • replace(string, pattern, replacement) -> string
      • subString(string, start, end) -> string
      • regExp(regexExpression, Options) -> string
        • regexExpression
          • pattern: [Regex Pattern]
          • flags: [Regex Flags]
        • Options
          • type: match, test, replace
          • str: string
          • replace?: string
      • regex(pattern, flags, string) -> function
        • match() -> string
        • test() -> boolean
        • replace(string, replace) -> string

Options

If tiny.config.json dose not exist in root (./), it extends Default.

| Option | Description | Default | | ------------------------ | ---------------------------------- | ------- | | allowEval | Allow eval() feature | false | | allowJavaScript | Allow js() feature | false | | useStdLibAutomatically | Use standard library automatically | false | | stderrPrefix | Prefix for stderr | true | | stderrColor | Color for stderr | true | | locale | Locale | en |

Npm package

Warning

Some features may not be updated immediately.

when updating fatal errors, npm package is also updated immediately.

npm i @tsukiroku/tiny
import Tiny, { NULL } from '@tsukiroku/tiny'

console.log(
    new Tiny('let x = "World!"; println("Hello, " + x);', {
        useStdLibAutomatically: true,
    })
        .setBuiltins(new Map([['test', () => NULL]]))
        .applyBuiltins()
        .eval()
)

@std/ must exist in root (./).

curl -O https://raw.githubusercontent.com/tsukiroku/tiny/main/scripts/dl-stds.sh && . ./dl-stds.sh && rm ./dl-stds.sh

Examples


Documentation

For examples, see Examples

Variables

let <identifier> = <expression>;

<identifier> = <expression>;

extends <expression>


let foo = 1;

foo = 2;

variable names use camelCase or snake_case and, cannot use numbers as variable prefixes.

Data types

string

'Hello, World!'
"안녕, 세상아!"

Can start the string with ' or ", and the content supports all Unicode.

number

12345

3.141592

boolean

true, false

To convert another value to a boolean value, you can use the boolean, or use the !! prefix.

array

[1, 2, 3, 'Foo', 'Bar', [1, 2, 3]]

[1, 2, 3][1]    // 2

[1, 2, 3] <- 1  // 2

Array elements can be accessed via the index or element operator.

object

let object = {
    'foo': 'bar',
    bar: false,
    baz: [1, 2, 3],
    5: {
        x: func() {
            return 1;
        }
    }
}

object['foo']      // 'bar'
object.bar         // false
object <- 5 <- x() // 1

object <- qux      // UNDEFINED

Object is a pair of keys and values.

the key must be of type string or number, and the value can be any type.

object pairs are can be accessed via the index or element operator.

function

<arguments>: <identifier>, <identifier>, ...

func <identifier>(<arguments>) <block expression>;

func(<arguments>) <block expression>;

extends <block expression>


func foo(a, b) {
    return a + b;
}

let bar = func(a, b) {
    return a + b;
};

Functions can be declared with hard coding, and supports anonymous functions.

function names use camelCase or snake_case and, cannot use numbers as variable prefixes.

null

null

undefined

void <expression>

extends <expression>

Returns undefined after executing the expression.

Operators

<operator>: +, -, *, /, %, ==, !=, <, >, <=, >=, <-, ., ??, in

<left expression> <operator> <right expression>

extends <expression>


+ (Plus) Operator

The + operator is addition, and can add number, string, array, object.

number + number : Add the right operand to the left operand.

string + string : Concatenate the right operand to the left operand.

array + array : Concatenate the right operand to the left operand.

object + object : Add the right operand to the left operand. if there are duplicate keys, the right operand is overwritten.

- (Minus) Operator

The - operator is subtraction, and can subtract number.

* (Multiply) Operator

The * operator is multiplication, and can multiply number.

/ (Divide) Operator

The / operator is division, and can divide number.

% (Modulo) Operator

The % operator is modulo, and can modulo number.

==, !=, <, >, <=, >= Operators

The ==, !=, <, >, <=, >= operators are comparison operators, and can compare any type.

<-, . Operator

The element operator, which can access array or object elements.

[1, 2, 3] <- 1       // 2

[1, 2, 3].1          // 2

let object = {
    foo: {
        bar: 'baz'
    },
};

object <- foo <- bar   // 'baz'
object.foo.bar         // 'baz'

object['foo']['bar'] = 'qux';

Cannot reassign values ​​with the element operator, must use index.

Control flow

If

if <condition expression [boolean]> <block expression>
else <block expression>

if <condition expression [boolean]> <expression> else <expression>

extends <block expression>


if (condition) {
    implement();
} else if (condition) {
    implement();
} else implement();

Can use if, else and else if.

the condition of if is a boolean value, non-boolean values ​​should use !!.

!!2    // true
!!0    // false
!!null // false

While

while <condition expression [boolean]> <block expression>

extends <block expression>


while (condition) {
    implement();
}

If condition is true, the block expression is executed.

the condition of while is a boolean value, non-boolean values ​​should use !!.

does not support break and continue. This can be used with forEach.

Import

<use> <string>;

extends string


use './module/myLib';

Executes external source code and can import executed environments.

path follows the project root (default ./).

if .tiny is not included in path, .tiny will be added automatically.

Decorator

@<object>
<function> // func <identifier>(<arguments>) <block expression>;

extends <object>, <function>


let myObject = { foo: 'bar' };

@myObject
func myFunc() {
    println(this <- decorator <- foo);
}

myFunc();

decorator starts with the prefix @ and requires a object value.

after that, a function is required, anonymous functions cannot be used.

Built-in functions

import

import("./module/myLib");

extends import

eval

eval("5 + 5"); // 10

Execute the provided code. The code can access the current environment variable.

allowEval must be true.

this feature is a dangerous feature. be careful.

js

js("console.log('foo')");

allowJavaScript must be true.

this feature is a dangerous feature. be careful.

options

options(); // object

Get project options. this cannot be modified.

Standard library

IO

print

println("Hello, World!", 10);

Prints the provided value.

println

println("Hello, World!");

Prints the provided value with a new line (\n).

Utility

length

length([1, 2, 3]); // 3

length("Hello, World!"); // 13

Gets the length of an array or string.

match

println(match(3, [
    [ 1, func(v) { return value + 1; } ],
    [ 2, func(v) { return value + 2; } ]
], func(v) {
    println('nothing');
    return v * 10;
}));

to_s, to_n, to_b, to_a

to_s(1); // '1'
to_n('1'); // 1
to_b(1); // true
to_a({ foo: 'bar', bar: 1 }); // ['bar', 1]

ternary

ternary(true, "foo", "bar"); // "foo"
ternary(false, "foo", "bar"); // "bar"

If the supplied value is true, the left parameter is returned, otherwise the right parameter is returned.

Array

let arr = [1, 2, 3];

Arrays can contain values ​​of any type.

extends array

push

push(array, 4); // [1, 2, 3, 4]

Adds the provided values ​​to an array.

Since this is a deep copy, array is not changed.

pop

pop(array); // [1, 2]

Removes the last element of an array.

Since this is a deep copy, array is not changed.

shift

shift(array); // [2, 3]

Removes the first element of an array.

Since this is a deep copy, array is not changed.

unshift

unshift(array, 0); // [0, 1, 2, 3]

Adds the provided values ​​to the beginning of an array.

Since this is a deep copy, array is not changed.

slice

slice(array, 1, 3); // [2, 3]

Divide array by the range of the two provided parameters.

Since this is a deep copy, array is not changed.

join

join(array, ", "); // "1, 2, 3"

Adds array to the provided string.

Since this is a deep copy, array is not changed.

forEach

forEach(array, func (value, index) {
    println(index, value);
});

Iterate through the array.

callback is given a value to traverse and an index value.


forEach(true, func (i) {
    if (i % 2 == 0) { return true };

    if (i >= 10) { return false };

    println(i);
});

forEach can be used as a while statement.

provide a true value instead of an array for the parameter, and the index value is provided in the callback.

repeat

repeat(5); // [NULL, NULL, NULL, NULL, NULL]

repeat("foo", 3); // ["foo", "foo", "foo"]

If there is one parameter provided, iterates the null value by the number of provided values,

if there are two parameters, it iterates the first parameter by the second parameter.

reduce

reduce([ 1, 2, 3 ], func (prev, curr) prev + curr, 0);

Iterates through each element of the provided array, accumulating the return value of the callback and returning it.

can specify the initial value of the accumulated values.

map

map([1, 2, 3], func (x, _) x * 10);

Iterates through each element of the provided array, returning a new array with the return value of the callback.

String

split

split("foo bar baz", " "); // ["foo", "bar", "baz"]

Splits the supplied string into the second parameter.

concat

concat("foo", "bar", "baz"); // "foobarbaz"

Combines the provided parameters.

replace

replace("foo bar baz", " ", ", "); // "foo, bar, baz"

Replaces the value of the second parameter in the provided string with the value of the third parameter.

subString

subString("foo bar baz", 4, 7); // "bar"

Divides a string by the number of parameters provided.

regex

let pattern = regex('[a-z]', 'g', 'asdf');

println(pattern <- match());
println(pattern <- test());
println(pattern <- replace('b'));

Expression

<expression>;

expr keyword

expr <expression>

extends expression

Evaluates the expression, and if the result is an error,

{
    'message': 'error message',
    'filename': 'file name',
    'line': 0,       // line number
    'column': 0,     // column number
    'error': true    // true if error
}

an Object containing the error message is returned.

Block Expression

<keywords> {
    implement();
}

<keywords> implement();

extends <keywords>, <if>

IIFE (Immediately Invoked Function Expression) pattern

(func () {
    implement();
})();

Statement

<let>, <return>, <while>, <block expression>, <expression statement>

extends <let>, <return>, <while>, <block expression>, <expression statement>

Keywords

<let>, <func>, <true>, <false>, <if>, <else>, <return>, <while>, <in>, <typeof>, <null>, <throw>, <delete>, <use>, <void>, <expr>

Not used, but may be added later

<class>, <for>, <const>

extends <let>, <func>, <true>, <false>, <if>, <else>, <return>, <while>, <in>, <use>, <void>, <expr>


typeof

<typeof> <expr>

Returns the type of the given expression.

typeof 10; // NUMBER
typeof 'foo'; // STRING
typeof true; // BOOLEAN
typeof {}; // OBJECT
typeof []; // ARRAY
typeof null; // NULL
typeof func() {}; // FUNCTION

null

null; // NULL

throw

<throw> <expr>

Throws an error in the provided expression.

throw 'Error'; // Error

delete

<delete> <expr>

Deletes the provided key from environment variables.

let a = 10;

delete a;

a; // Identifier 'a' is not defined.

Return

<keywords> {
    implement();

    return null;
} // `NULL`

<if> null; // `NULL`

Returns a value.

extends <keywords>, <if>, <block expression>