Skip to content

Latest commit

 

History

History
490 lines (376 loc) · 11 KB

Start.md

File metadata and controls

490 lines (376 loc) · 11 KB

Start

Index / Reference

Jsi is a javascript-ish interpreter with builtin websocket-server, sqlite and C-extensibility.

Get the source and build '''make'''.

Or download a binary for (https://github.com/pcmacdon/jsibin/).

🚩 See Building.

Basics

Jsi implements most of Ecma-script 5.1 (see Compatibility) with deviations.

Functions

Function arguments may use types / defaults:

function foo(a:number, b:string='') {}
function bar(a,b) {}

🚩 See Functions.

Arrow functions are also supported.

var f = (x,y) => { puts(x,y); };
var g = (x,y) => x*y;

+++ Arrow Limitations

Jsi's simple parser requires that single-args have no braces:

var e =  (x,y)  => { return x*y; }; // CORRECT
var f =  x  => { return x*2; };     // CORRECT
var g = (x) => { return x*2; };     // ERROR!

Also, arrow function parameters can not have types.

++++

Variables

Variables can be declared using:

var x = 0;
const z = 0;
let y = 0;

Note however that let does the same thing as var: it is not scoped.

Objects

Shorthand object initializers are accepted, but the first element must use a colon:

var b = 1, c = 2;
var o = {a:1, b, c, myfunc() { return 1;} };

Also, an extended Object.freeze is supported.

Modules

Using module/moduleOpts provides option parsing, help, and command invocation.

// FILE: add.jsi
function add(args, ...) {
    const options = { // Concat args into list.
        name:'',    // Name prefix.
        start:0,    // Start position.
    };
    var self = {
        max:4,
    };
    moduleOpts(options, self);
    return [args, self];
}
module(add);
jsish add.jsi a b c -name dog
[ [ "a", "b", "c", "-name", "dog" ], { max:4, name:"", start:0 } ]
jsish add.jsi -h
/tmp/add.jsi:9: help: ...
Concat args into list.
Options are:
	-name		""		// Name prefix. {}
	-start		0		// Start position.

Accepted by all .jsi modules: -Debug, -Trace, -Test, -Assert.

🚩 See Modules.

Output

Following are examples of input and output in Jsi.

Command-line arguments:

jsish -e 'puts("hi", console.args);' -a 1 -b 2 x y z
hi [ "-a", "1", "-b", "2", "a", "b", "c" ]

User input:

var line = console.input();
puts(line);

Output:

// FILE: output.jsi
puts('puts outputs a string');
printf('printf omits newline\n');
log('log adds line info');
console.puts('console versions go to stderr');
jsish output.jsi
puts outputs a string
printf omits newline
output.jsi:4:   "log adds line info", 
console versions go to stderr

File I/O:

// FILE: myio.jsi
File.write('myfile.txt', 'some data');
var data = File.read('myfile.txt');
var ch = new Channel('myfile.txt');
puts(ch.read());

See Input/Output below.

Includes

Include other code using: source, import, load, require:

source

source includes a javascript file and evaluates inline:

source('src1.jsi');
source(['src2.jsi','src3.jsi']);
var fun = source('fun.jsi');
fun(1);

Not the use of return:

// FILE: fun.jsi
return function(n) {n+1;}

import

import is like source except it executes code in an function-closure.

var ret = import('exp.jsi');
ret.foo();

The import-ed code typically uses export default.

// FILE: exp.jsi
function foo() {}
function bar() {}
export default *

+++ Forms of Export:

Four forms of export are supported:

export default * // All functions
export default + // ALl functions and vars
export default {func1:func1, func2, func3, var1}

var exps = {func1:func1, func2, func3};
export default exps

Note:

  • export must be the final statement.
  • export is the same as return, but needs no semicolon.
  • in the above, only the last two forms are ES 6 compatible.

+++

load

Use load for compiled shared libraries:

load('Baker.so'); // or .dll

🚩 See Loadable Extensions.

require

require just invokes source/load and is described in modules require.

Help

Jsi has command-line help:

jsish -h
USAGE:
  jsish [PREFIX-OPTS] [COMMAND-OPTS|FILE] ...

PREFIX-OPTS:
  --E CODE	Javascript to evaluate before program starts
  --I OPT=VAL	Interp option bits: equivalent to Interp.conf({OPT:VAL}); VAL defaults to true.
  --T 		SApply testMode transforms showing their output: a shortcut for --I testMode=1

COMMAND-OPTS:
  -a		Archive: mount an archive (zip, sqlar or fossil repo) and run module.
  -c		CData: generate .c or JSON output from a .jsc description.
  -d		Debug: console script debugger.
  -e CODE	Evaluate javascript and exit.
  -h ?CMD?	Help: show help for jsish or its commands.
  -m		Module: utility create/manage/invoke a Module.
  -s		Safe: runs script in safe sub-interp.
  -t		Testing of scripts or directories of scripts with .js/.jsi extension.
  -w		Wget: web client to download file from url.
  -v		Version: show version detail: add an arg to show only X.Y.Z
  -z		Zip: append/manage zip files at end of executable.
  -D		DebugUI: web-gui script debugger.
  -J		JSpp: preprocess javascript for web.
  -S		SqliteUI: web-gui for sqlite database file.
  -W		Websrv: web server to serve out content.

Interp options may also be set via the confFile.'

as well as interactive help:

jsish
Jsish interactive: see 'help [cmd]'.  \ cancels > input.  ctrl-c aborts running script.
$ help load
load(shlib:string):void
Load a shared executable and invoke its _Init call.

Options

The --I is used to set internal Interp options:

jsish --I traceCall=func hello.jsi

Two forms of command-line eval include -e:

jsish -e 'var i = 0; while (i++<10); return i;'

which exits after the eval and --E which does not:

jsish --E 'require("Sqlite");` hello.jsi

Two Debuggers are available: command-line and GUI.

jsish -d buggy.jsi
jsish -D buggy.jsi

The builtin Testing feature is invoked with -t:

jsish -t hello.jsi
[PASS] hello.jsi 	 (16.5791015625 ms)

or --T to just see output.

jsish --T hello.jsi 
[ [], { a:1, b:2, c:"a" } ]

Most other options invoke script application zip-appended onto the jsish binary.

Diagnostics

Logging

Logging provides conditional output useful in diagnosing problems:

jsish -W -Trace true wspage.html 
Websrv.jsi:214:  "TRACE: PORT IS: 37667", OpenWebsock()
Websrv.jsi:506:  "TRACE: Listening on port: 0", main()
Websrv.jsi:276:  "TRACE: URL:  http://127.0.0.1:37667/Websrv/wspage.html", OpenBrowser()
Websrv.jsi:80:  "TRACE: FILTER: /Websrv/wspage.html true", WsFilter()
...

🚩 See Logging.

Backtrace

Upon encountering an uncaught error, a backtrace is generated, with most recent call last:

jsish -W
CALL BACKTRACE:
#1: Websrv.jsi:531:  in moduleRun()
#2: Websrv.jsi:526:  in Websrv( [], {} )
#3: Websrv.jsi:472:  in main()

/zvfs/lib/Websrv.jsi:472: error: throw near url file empty or not found: 
ERROR: 

Tracing

Enable tracing lets you see calls and returns:

jsish --I traceCall=func,ret hello.jsi
hello.jsi:2:   "#1: > hello() 
hello.jsi:2:   "#1: < hello() 
 <-- [ [], { a:1, b:2 } ][ [], { a:1, b:2 } ]

Input/Output

The following are used for output and input:

Command Description
puts Quotes arguments to stdout
printf Formatted output to stdout
log Like puts but including file/line info
console.* Versions of above commands that output to stderr
File File related commands
Channel Output to stderr/stdout channels

See System and console for details. All commands except printf automatically add a newline.

puts

Quotes all arguments and outputs them to stdout.

puts("Batman begins");
var X = {a:1, b:"two"};
puts(X);
puts(X.a, X.b);
Batman begins
{ a:1, b:"two" }
1 two

printf

Processes arguments according to format and outputs to stdout.

printf("Batman begins: %d %S\n", X.a, X.b);

log

: Works much like puts, but includes the current file, line and function.

log("Batman begins");
"Batman begins", file.jsi:1, func()

In addition, when the first argument to log is a boolean, output appears only if true.

log(false, "Batman begins");
log(true, "Batman begins");
"Batman begins", file.jsi:2, func()

console

The console commands output to stderr:

console.puts("Batman begins");
console.printf("Batman begins: %d %S\n", X.a, X.b);
console.log("Batman begins");

File

The File commands also handle input/output:

File.write('myfile.txt', 'hello');
var x = File.read('myfile.txt');

Channel

The Channel commands handles program I/O:

File.write('stderr', 'hello');
var fp = new Channel('stderr');
fp.puts('hello');

Compatibility

Jsi implements most of Ecma-script 262 standard version 5.1 with numerous additions, ommissions and deviations:

  • Additions:
    • Functions parameters with types and defaults.
    • ES6 features: =>, for of, const, and let (but unscoped like var).
    • Info, Interp, and other system builtins.
  • Omissions:
    • no Semicolon Insertion.
    • no Error (arg to catch is a string).
    • no Date (supplanted by strftime/strptime).
  • Deviations:
    • typeof[] == "array" and typeof null == "null",
    • Backticks work like normal strings (ie. ignores ${}).
    • UTF supported in strings, not code.
    • Prototype implementation is incomplete.

The main syntactic difference is semicolons are required:

function foo() {
    var x = 1;
    return ++x;
}

not

function foo() {
    var x = 1
    return ++x
}

Conditionals

Jsi will check for undefined vars used on the left-hand side (LHS) of conditional expressions. To such avoid errors, put the var on the RHS.

// FILE: us.jsi
var x;
if ('' === x) puts('x empty'); //OK.
if (x === '') puts('x empty');
/tmp/us.jsi:4: error: lhs value undefined in ===/!==
ERROR

Shortcomings

The following is a known memory leak:

var x = {};
x.x=x;

Solving this would require python style garbage collection: http://www.arctrix.com/nas/python/gc/.

*[JSish]:JS-ish, or Jsi for short, is a Javascript-Like Interpreter