Getting Started

CodeFactor NPMVersion

Install with npm i -g entropy-script

Run a script with entropy-script <filename>.es or jses <filename>.es

Installation

NPM

npm i -g entropy-script

To install Entropy Script globally on your computer, or

npm i entropy-script

To install the source code in the current directory as an NPM package

From Source

You can also use it from the source code on GitHub.

CLI

The CLI can be accessed with either entropy-script or jses commands. Note that jses is used where either could be used.

Start the REPL with jses. Type exit to exit the REPL.

jses [script] [args]

The most common use case is, of course, a simple invocation of a script:

jses myscript.es

Syntax

The syntax of EntropyScript is very similar to JavaScript, except that is has slightly fewer brackets.

An EntropyScript script is a list of statements (a statements) seperated by the ;. All lines must have semicolons except the last line in a statements.

Declaration

To declare a constant, say

let n = something;

To declare a mutable variable, say

let var n = something;

You must declare variables before using them. This would result in an InvalidSyntaxError:

n = something;

You can also declare global variables like this:

// global constant
let global n = something;

// global mutable variable
let global var n2 = somethingelse;

If

if expression {
	
}

Will run if expression evaluates to true. Can be combined with else like so:

if expression {
	// do something
	
} else if another_expression {
	// do something else
	
} else {
    // do a something different
}

You can also use ifs similarly to ternary operators, such as:

let my_val = if true { 'hello' } else { 'bye' };
my_val; // 'hello'

Loops

For

for i in expression {
    
}

The for loop is very versatile, as it can be used to iterate over an array but also over numbers, strings and the keys of objects.

// iterate from 0-9
for j in 10 {
	
}

// iterate from 3-9 with a step of 2
for l in range(3, 9, 2) {
	
}

let my_object = { a: 1, b: 2 };
// iterate over the array ['a', 'b']
for key in my_object {
	let value = my_object[key];
}

While

while expression {
	
}

Will repeat until the expression something evaluates to false

var a = false;
while !a {
    a = true;
}

You cannot write for, if or while statements in the common C-like way:

// InvalidSyntaxError
if (expression) 
	do_something();

You must have curly braces.

Comments

Like JavaScript, you write comments as follows

// single line comment

/*
    Multi-line comment
 */

Functions

You can declare functions like so

func do_something () {

};
// Note the ';'

Or anonymously like this

let do_something = func () {};

Classes

Declare classes like so

class MyClass {};
// or
let MyOtherClass = class {};

All classes and types should be in PascalCase

Methods

The body of the class can only contain methods, which are declared like so:

let MyClass = class {
    // method
    do_something () {
        // do something
    }
};

All methods and properties are public.

Constructor

The constructor gets called once when the instance is created.

class MyClass {
    // constructor 
    init () {
        this.a = 1;
    }
    
    // method
    get_a () {
        return this.a;
    }
};

let my_instance = MyClass();
my_instance.get_a(); // 1

Simply call the class like a function to create an instance. No new keyword.

Operator overrides

class Num {
    init (n: Number) {
        this.a = n;
    }
    
    __add__ (to: Number) {
    
    }
};

Num(1) + Num(2);
// Num(3);

The overrideable methods are:

Method NameOperator
__add__+
__subtract__-
__multiply__*
__divide__/
__pow__^
__eq__==
__gt__>
__lt__<
__or__||
__and__&&
__pipe__|
__ampersand__&
__bool__!! and any other bool conversion
__set_property__[] and .
__get_property__[] and .
__call__()

Built In

Global Constants

true

false

nil

Type

String

Number

Func

Array

Any

Bool

Object

Error

Undefined

Built-In Functions

* Only in Node runtimes

range

range: func (from: Number, to: ?Number, step: ?Number) Array[Number];

Same as Python's range function. Returns an array of numbers.

parse_num

parse_num: func (value: String) Number;

Parse floats or integers into numbers

import

import: func (path: String) Any;

Imports a module and returns the value. Slightly different behaviour between Node and browser runtimes:

  • All imports must be declared in config file for browsers, which then get preloaded before runtime

help

help: func (value: Any) String;

Returns a string with information on the passed object.

print

print: func (*: Array[Any]) nil;

Calls the specified print function. Often just native console.log.

log

log: func (*: Array[Any]) nil;

Calls native console.log

delete

delete: func (symbol: String) nil;

Removes a symbol with the specified identifier.

path

__path__: func () String;

Returns The current path

symbols

__symbols__: func (recursive: ?Bool) Object;

Gets all symbols in the current scope. If recursive is true, then gets all symbols up the global context.

using

using: func (module: Any) nil;

Adds all symbols from object or namespace to the current scope.

throw

throw: func (name: String, detail: String) nil;

Throws an error of type name.

sleep

sleep: func (ms: Number, then: func (*: Array[Any]) Any) nil;

open *

open: func (path: String, encoding: ?String = 'utf-8') ({
    str: func () String,
    write: func (data: String) nil,
    append: func (data: String) nil
})};

Throws ImportError if the file doesn't exist.

Built In Modules

json

ascii

time

math

promise

fs

https

http

mysql

path

Primitives

Everything in EntropyScript is a primitive. There are a few built in primitives, and then all new types inherit from primitive.

Methods

str

str: func () String;

Returns a stringified version of the primitive

cast

cast: func (t: Any) t | Error;

Tries to cast to that type. If you cannot cast the object or cannot cast to that type, then it will throw an error.

bool

bool: func () Bool

Evaluates the object as a boolean.

is

is: func (o: Any) Bool;

Returns true if the two are the same object.

let a = 1;
a.is(a); // true
a.is(1); // false
let b = a;
a.is(b); // true
b.is(a); // true

isa

isa: func (type: Any) Bool;

Returns true if the object is of type type

has_property

has_property: func (key: Any) Bool;

Returns true if the object has a key which is equal to key

describe

describe: func (description: String) Undefined;

Adds a description to the object. Does nothing when run on built in objects.

type_check

type_check: func (obj: Any) Bool;

Reverse of isa. Returns true if obj is of type of whatever was called on.

clone

clone: func () Any;

Returns a clone of the object

Properties

type

The object's type.

self

The object

info

The metadata about the object, including its description

value

The object

Type

Type: Type

Every EntropyScript class and built-in type is an instance of Type. Create an instance of a type by calling it. Call a built-in type to cast to that type.

Call Type to get the string of the type of something, and without any parameters to create a new empty class.

Type(String);        // 'Type'
Type('hello world'); // 'String'
Type(Type);          // 'Type'
Type(Type(Type));    // 'String'
Type();              // new type

TypeUnion

Is the 'Union' of two types. Create with the pipe | operator. Resolves true if the resolution of either child type resolves to true

TypeIntersection

Is the 'Intersection' of two types. Create with the pipe & operator. Resolves true if the resolution of both child type resolves to true.

This is different from the TypeScript equivalent & as it does not use the true intersection of the types, operating more like the && operator.

TypeNot

Is the 'Not' of a type expression. Create with the ~ before the type expression.

Number

Number: Type;

Number is for both integers and floating point numbers.

Methods

(None)

Properties

(None)

String

String: Type

Create a string with ', ` or ". All are equivalent. Declaring strings is similar to string literals in other languages.

'hi
';

Is fine and is equivalent to

'hi\n';

To escape the string, use \ backslash; for example

'Here\'s a string';

Methods

len

len: func () Number;

Returns the length of the string

Properties

(None)

Array

Array: Type;

Arrays can be declared with square brackets, elements delimited by a comma.

For example, an array of numbers:

let my_array = [0, 1, 2, 3];

You can mix types in array and even nest arrays.

let my_nested_array = [0, 'hello world', [2, 3, [4]]];

To type an array use this syntax:

let my_array_of_numbers: Array[Numbers] = [0, 1, 2];

// throws a TypeError
let my_erronious_array_of_numbers: Array[Numbers] = [0, 1, 'hi'];

// And then nested types
let my_nested_array_of_numbers: Array[Array[Numbers]] = [[0, 2], [1, 3]];

You can also declare Tuple types with arrays like so:

let tuple = [String, Number];

let my_tuple: tuple = ['hello', 0];

// TypeError
let my_bad_tuple: tuple = ['hello', 'world'];

Methods

len

len: func () Number;

The length of the array

contains

contains: func (element: Any): Bool;

Returns true if the array contains an element which is equivalent to element

Properties

Error

Error: Type;

Methods

(None)

Properties

name

name: String;

The name of the error, for example, 'TypeError' or 'InvalidSyntaxError'

detail

detail: String;

More details about the error

traceback

traceback: Array[String];

An array of strings which are the name and location of function from which the error was generated.

Function

Func: Type;

Declare a function with the func keyword.

To type check against a function, you can simply check if something is a function:

let my_func: Func = func () {};

// TypeError
let not_a_func: Func = 0;

Or you can do a deeper type heck and check against the parameters and return type:


let my_func: (func () Undefined) = func (): Undefined {};

/*
  Note the lack of a colon after the brackets in the type description.
  The return type of the type function is simply a function which 
  returns the desired return type.
  Technically, you could have side effects inside the type function, 
  although this is ill-advised.
*/


// TypeError
let my_func: (func () Undefined) = func (): Undefined { 
    return 1;
};


// Note that you must explicitely type the return value and parameters 
// of both the type and the value:

// TypeError
let my_func: (func () Number) = func () 0;

// ok
let my_func: (func () Number) = func (): Number 0;

Examples

Here are some examples of EntropyScript in action.

FizzBuzz to n

let now = import('time').now;

const main = func (n) {
    for i in range(1, n+1) {

        div3 = i % 3 == 0;
        div5 = i % 5 == 0;

        if div3 && div5 {
            print('fizzbuzz');
        } else if div3 {
            print('fizz');
        } else if div5 {
            print('buzz');
        } else {
            print(i);
        }
    }
};

// time how long it takes
let start = now();
main(1000);
print(now() - start, 'ms');

This typically runs in ~150ms, compared to ~50ms for Python and JavaScript

Fibonacci series up to n

let fib = func (n) {
    var a = 0;
    var b = 1;

    while a < n {
        print(a);
        let t = a;
        a = b;
        b = t + b;
    }
};

fib(1000);