UNPKG

@tsukiroku/tiny

Version:
1,130 lines (783 loc) 25.8 kB
- [Introduce](#introduce) - [Start REPL](#start-repl) - [REPL commands](#repl-commands) - [Web Playground](#web-playground) - [Interpreter](#interpreter) - [Tokens](#tokens) - [Expressions](#expressions) - [Statements](#statements) - [Priority](#priority) - [Operators](#operators) - [Literal](#literal) - [Built-in functions](#built-in-functions) - [Standard library](#standard-library) - [Options](#options) - [Npm package](#npm-package) - [Examples](#examples) - [Documentation](#documentation) <br /> # Introduce <br /> ## Start REPL ```sh # Install dependencies npm i # REPL npm run start:repl # You can also from a file. npm run start:repl [file] ``` <br /> ## REPL commands `//command ...args` | Command | Description | | ------- | -------------------------------------------------- | | `exit` | Exit the repl | | `mode` | Change the mode (`repl`, `lexer`, `parser`, `env`) | <br /> # Web Playground [README](./web) | [Playground](https://tsukiroku.github.io/tiny) <br /> # 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` | `'` | <br /> ## 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` | <br /> ## Statements | Statement | Syntax | Statement | Syntax | | --------- | ------------------- | --------- | ----------------------- | | `Let` | `let ident = expr;` | `While` | `while (expr) [block];` | | `Return` | `return expr;` | `Block` | `{ statement }` | <br /> ## 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` | <code>Logical (&&, &#124;&#124;)</code> | | `2` | `Assignment (=)` | | `1` | `...` | <br /> ## 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` | <br /> ## 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]` | <br /> # 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`](#regex) | | <br /> # Standard library - [**`@std/`**](https://github.com/tsukiroku/tiny/blob/main/@std/) - [`lib`](https://github.com/tsukiroku/tiny/blob/main/@std/lib.tiny) - [`io`](https://github.com/tsukiroku/tiny/blob/main/@std/io.tiny) - `print(args*) -> NULL` - `println(args*) -> NULL` - [`array`](https://github.com/tsukiroku/tiny/blob/main/@std/array.tiny) - `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`](https://github.com/tsukiroku/tiny/blob/main/@std/util.tiny) - `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` <br /> # 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` | <br /> # Npm package > **Warning** > > Some features may not be updated immediately. > > when updating fatal errors, [npm package](#npm-package) is also updated immediately. ```sh npm i @tsukiroku/tiny ``` ```ts 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 (`./`). ```sh curl -O https://raw.githubusercontent.com/tsukiroku/tiny/main/scripts/dl-stds.sh && . ./dl-stds.sh && rm ./dl-stds.sh ``` <br /> # Examples - [**`./examples`**](https://github.com/tsukiroku/tiny/tree/main/examples) - [`Hello, World!`](https://github.com/tsukiroku/tiny/blob/main/examples/hello_world.tiny) - [`Fibonacci`](https://github.com/tsukiroku/tiny/blob/main/examples/fibonacci.tiny) - [`Function`](https://github.com/tsukiroku/tiny/blob/main/examples/function.tiny) - [`Object`](https://github.com/tsukiroku/tiny/blob/main/examples/object.tiny) - [`If`](https://github.com/tsukiroku/tiny/blob/main/examples/if.tiny) - [`While`](https://github.com/tsukiroku/tiny/blob/main/examples/while.tiny) - [`Import`](https://github.com/tsukiroku/tiny/blob/main/examples/import.tiny) - [`Variable`](https://github.com/tsukiroku/tiny/blob/main/examples/variable.tiny) - [`Operators`](https://github.com/tsukiroku/tiny/blob/main/examples/operators.tiny) - [`Built-in functions`](https://github.com/tsukiroku/tiny/blob/main/examples/builtin.tiny) - [`Decorators`](https://github.com/tsukiroku/tiny/blob/main/examples/decorators.tiny) - [`StdLib`](https://github.com/tsukiroku/tiny/blob/main/examples/stdlib) - [`Array`](https://github.com/tsukiroku/tiny/blob/main/examples/stdlib/array.tiny) - [`IO`](https://github.com/tsukiroku/tiny/blob/main/examples/stdlib/io.tiny) - [`String`](https://github.com/tsukiroku/tiny/blob/main/examples/stdlib/string.tiny) - [`Utility`](https://github.com/tsukiroku/tiny/blob/main/examples/stdlib/util.tiny) <br /> --- <br /> # Documentation - [Variables](#variables) - [Data types](#data-types) - [string](#string) - [number](#number) - [boolean](#boolean) - [array](#array) - [object](#object) - [function](#function) - [null](#null) - [undefined](#undefined) - [Operators](#operators-1) - [`+` (Plus) Operator](#-plus-operator) - [`-` (Minus) Operator](#--minus-operator) - [`*` (Multiply) Operator](#-multiply-operator) - [`/` (Divide) Operator](#-divide-operator) - [`%` (Modulo) Operator](#-modulo-operator) - [`==`, `!=`, `<`, `>`, `<=`, `>=` Operators](#------operators) - [`<-`, `.` Operator](#---operator) - [Control flow](#control-flow) - [If](#if) - [While](#while) - [Import](#import) - [Decorator](#decorator) - [Built-in functions](#built-in-functions-1) - [import](#import-1) - [eval](#eval) - [js](#js) - [convert](#convert) - [options](#options-1) - [Standard library](#standard-library-1) - [IO](#io) - [print](#print) - [println](#println) - [Utility](#utility) - [length](#length) - [match](#match) - [string, number, boolean](#string-number-boolean) - [ternary](#ternary) - [Array](#array-1) - [push](#push) - [pop](#pop) - [shift](#shift) - [unshift](#unshift) - [slice](#slice) - [join](#join) - [forEach](#foreach) - [repeat](#repeat) - [reduce](#reduce) - [map](#map) - [String](#string-1) - [split](#split) - [concat](#concat) - [replace](#replace) - [subString](#substring) - [rTest](#rtest) - [rMatch](#rmatch) - [Expression](#expression) - [Block Expression](#block-expression) - [Statement](#statement) - [Keywords](#keywords) - [typeof](#typeof) - [null](#null) - [throw](#throw) - [delete](#delete) - [Return](#return) For examples, see [`Examples`](./examples/README.md) <br /> # Variables ``` let <identifier> = <expression>; <identifier> = <expression>; ``` > extends [`<expression>`](#expression) --- ``` let foo = 1; foo = 2; ``` --- variable names use `camelCase` or `snake_case` and, cannot use numbers as variable prefixes. <br /> ## Data types ### string ``` 'Hello, World!' "안녕, 세상아!" ``` --- Can start the string with `'` or `"`, and the content supports all [`Unicode`](https://en.wikipedia.org/wiki/Unicode). ### number ``` 12345 3.141592 ``` ### boolean ``` true, false ``` --- To convert another value to a boolean value, you can use the [`boolean`](#string-number-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) 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`](#string) or [`number`](#number), and the value can be any type. object pairs are can be accessed via the `index` or [`element`](#---operator) operator. ### function ``` <arguments>: <identifier>, <identifier>, ... func <identifier>(<arguments>) <block expression>; func(<arguments>) <block expression>; ``` > extends [`<block expression>`](#block-expression) --- ``` func foo(a, b) { return a + b; } let bar = func(a, b) { return a + b; }; ``` --- Functions can be declared with [`hard coding`](https://en.wikipedia.org/wiki/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>`](#expression) Returns `undefined` after executing the expression. <br /> # Operators ``` <operator>: +, -, *, /, %, ==, !=, <, >, <=, >=, <-, ., ??, in <left expression> <operator> <right expression> ``` > extends [`<expression>`](#expression) --- ## `+` (Plus) Operator The `+` operator is addition, and can add [`number`](#number), [`string`](#string), [`array`](#array), [`object`](#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`](#number). ## `*` (Multiply) Operator The `*` operator is multiplication, and can multiply [`number`](#number). ## `/` (Divide) Operator The `/` operator is division, and can divide [`number`](#number). ## `%` (Modulo) Operator The `%` operator is modulo, and can modulo [`number`](#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`. <br /> # Control flow ## If ``` if <condition expression [boolean]> <block expression> else <block expression> if <condition expression [boolean]> <expression> else <expression> ``` > extends [`<block expression>`](#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>`](#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`](#foreach). <br /> # Import ``` <use> <string>; ``` > extends [`string`](#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. <br /> # Decorator ``` @<object> <function> // func <identifier>(<arguments>) <block expression>; ``` > extends [`<object>`](#object), [`<function>`](#function) --- ``` let myObject = { foo: 'bar' }; @myObject func myFunc() { println(this <- decorator <- foo); } myFunc(); ``` --- `decorator` starts with the prefix `@` and requires a [`object`](#object) value. after that, a [`function`](#function) is required, anonymous functions cannot be used. <br /> # Built-in functions ## import ``` import("./module/myLib"); ``` > extends [`import`](#import) ## eval ``` eval("5 + 5"); // 10 ``` <br /> 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. <br /> # Standard library <br /> ## 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. <br /> ## Array ``` let arr = [1, 2, 3]; ``` Arrays can contain values ​​of any type. > extends [`array`](#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. <br /> ## 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`](#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>`](#keywords), [`<if>`](#if) IIFE (Immediately Invoked Function Expression) pattern ``` (func () { implement(); })(); ``` # Statement ``` <let>, <return>, <while>, <block expression>, <expression statement> ``` > extends [`<let>`](#variables), [`<return>`](./return), [`<while>`](#while), [`<block expression>`](#block-expression), [`<expression statement>`](#expression) # 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>`](#variables), [`<func>`](#function), [`<true>`](#boolean), [`<false>`](#boolean), [`<if>`](#if), [`<else>`](#if), [`<return>`](#return), [`<while>`](#while), [`<in>`](#operators-1), [`<use>`](#import-1), [`<void>`](#undefined), [`<expr>`](#expr-keyword) --- ## typeof ``` <typeof> <expr> ``` Returns the type of the given expression. <br /> ``` 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. <br /> ``` throw 'Error'; // Error ``` ## delete ``` <delete> <expr> ``` Deletes the provided key from environment variables. <br /> ``` let a = 10; delete a; a; // Identifier 'a' is not defined. ``` <br /> # Return ``` <keywords> { implement(); return null; } // `NULL` <if> null; // `NULL` ``` Returns a value. > extends [`<keywords>`](#keywords), [`<if>`](#if), [`<block expression>`](#block-expression)