Language - micojs/micojs.github.io GitHub Wiki

MicoJS is a growing subset of JavaScript.

Supported features

Variables

Declare mutable variables with let, constants with const. Old-style var is also supported.

let x = 1, y;
var z = x;
const w = 42;

Functions

Functions can be declared in the following ways:


function A(arg){
  return arg + 1;
}

const B = (arg) => {
  return arg + 1;
};

const C = arg => arg + 1;

Note that functions can be declared inside other functions, and that they can capture external variables like in standard JS:

function getAdder(X) {
  return Y => Y + X;
}
const add5 = getAdder(5);
debug("10 + 5 = ", add5(10));

Classes

This is the recommended syntax for declaring classes:

class C {
  constructor(arg) {
    this.property = arg;
  }
}

The old style should be avoided.

Flow control

Use standard JS syntax:

if (expr) {
  debug(expr, "is true");
} else if (expr2)
  debug(expr2, "is true");
else debug("all false");

debug(expr ? "expr is true" : "expr is false");

let arr = new Array(5); // create an array with 5 elements

for (let i = 0; i < arr.length; ++i) // C-style for
  arr[i] = i * 2;

for (let value of arr)
  debug(value); // prints 0, 2, 4, 6, 8, 10

for (let key in {min, max, clamp})
  debug(key); // prints min, max, and clamp

label: for(let i = 0; i < 100; ++i) {
  for (let j = 0; j < 100; ++j) {
    if (i == 3 && j == 7)
      break label; // break out of external for
    if (j == 10)
      break; // break out of internal for
  }
}

while (expr) { // loop until expr is not true
  debug(expr, "is still true");
}

do {
  debug("doing");
} while (expr);

Pragmas

Pragmas are strings that would appear to have no effect on a program, but can be used to configure the build system or compiler. The syntax is based on standard JS's "use strict".

set [flag] [value]

Sets the value of a single flag. The value should not contain spaces. "set version v0.0.1";

push [flag] [value1 value2 value3 ...]

Similar to set, but accepts multiple values, appending them to a flag. "push title Game Title";

ifeq [flag] [value] and ifneq [flag] [value]

Check a flag's value to define if a block should be compiled or not.

// platform is defined in std.js

{"ifeq platform blit";
 "include /src/blit.js";
 debug("Running on 32Blit");
}

{"ifeq platform pico";
 "include /src/pico.js";
 debug("Running on PicoSystem");
}

{"ifeq platform pokitto";
 "include /src/pokitto.js";
 debug("Running on Pokitto");
}

{"ifeq platform meta";
 "include /src/meta.js";
 debug("Running on Gamebuino Meta");
}

{"ifeq platform espboy";
 "include /src/espboy.js";
 debug("Running on ESPboy");
}

include /full/path/to/file.js

While the ES6 import something from './file.js'; syntax isn't supported yet, it is possible for one file to include another:

In "/source/Random.js":

function getRandomNumber() {return 5;}

In "/source/Main.js":

"include /source/Random.js";
debug(getRandomNumber());

Unsupported features

While the goal is to support as much of standard JS as possible, the priority is lower for features that would be particularly inefficient on microcontrollers with limited memory.

An example is that objects' sizes are currently fixed. Dynamically adding new properties to an object would require relocating that object once it becomes full. Support will be added for this in the future, but for now it is best to create objects with all of the necessary properties at once. The same applies to arrays.

Planned features

  • import use "include /path/to/file.js"; instead.
  • class C { property = 1; } - Use a constructor to define properties for now. Private properties currently not supported.
  • a = b?.c
  • switch(value)

Won't Do

  • try{ ... } catch(error){} - shouldn't be needed, MCUs typically abort on exceptions.
  • async and await, shouldn't be needed.
  • coroutines - shouldn't be needed.
  • Browser-compatible API (Math.*, console.*, Array.*, Object.*, etc.) - inefficient on MCUs.