"use strip"
;
import
*
as
std
from
"std"
;
import
*
as
os
from
"os"
;
(
function
(g) {
g.os = os;
g.std = std;
var
Object = g.Object;
var
String = g.String;
var
Array = g.Array;
var
Date = g.Date;
var
Math = g.Math;
var
isFinite = g.isFinite;
var
parseFloat = g.parseFloat;
var
config_numcalc = (
typeof
os.open ===
"undefined"
);
var
has_jscalc = (
typeof
Fraction ===
"function"
);
var
has_bignum = (
typeof
BigFloat ===
"function"
);
var
colors = {
none:
"\x1b[0m"
,
black:
"\x1b[30m"
,
red:
"\x1b[31m"
,
green:
"\x1b[32m"
,
yellow:
"\x1b[33m"
,
blue:
"\x1b[34m"
,
magenta:
"\x1b[35m"
,
cyan:
"\x1b[36m"
,
white:
"\x1b[37m"
,
gray:
"\x1b[30;1m"
,
grey:
"\x1b[30;1m"
,
bright_red:
"\x1b[31;1m"
,
bright_green:
"\x1b[32;1m"
,
bright_yellow:
"\x1b[33;1m"
,
bright_blue:
"\x1b[34;1m"
,
bright_magenta:
"\x1b[35;1m"
,
bright_cyan:
"\x1b[36;1m"
,
bright_white:
"\x1b[37;1m"
,
};
var
styles;
if
(config_numcalc) {
styles = {
'default'
:
'black'
,
'comment'
:
'white'
,
'string'
:
'green'
,
'regex'
:
'cyan'
,
'number'
:
'green'
,
'keyword'
:
'blue'
,
'function'
:
'gray'
,
'type'
:
'bright_magenta'
,
'identifier'
:
'yellow'
,
'error'
:
'bright_red'
,
'result'
:
'black'
,
'error_msg'
:
'bright_red'
,
};
}
else
{
styles = {
'default'
:
'bright_green'
,
'comment'
:
'white'
,
'string'
:
'bright_cyan'
,
'regex'
:
'cyan'
,
'number'
:
'green'
,
'keyword'
:
'bright_white'
,
'function'
:
'bright_yellow'
,
'type'
:
'bright_magenta'
,
'identifier'
:
'bright_green'
,
'error'
:
'red'
,
'result'
:
'bright_white'
,
'error_msg'
:
'bright_red'
,
};
}
var
history = [];
var
clip_board =
""
;
var
prec;
var
expBits;
var
log2_10;
var
pstate =
""
;
var
prompt =
""
;
var
plen = 0;
var
ps1;
if
(config_numcalc)
ps1 =
"> "
;
else
ps1 =
"qjs > "
;
var
ps2 =
" ... "
;
var
utf8 =
true
;
var
show_time =
false
;
var
show_colors =
true
;
var
eval_start_time;
var
eval_time = 0;
var
mexpr =
""
;
var
level = 0;
var
cmd =
""
;
var
cursor_pos = 0;
var
last_cmd =
""
;
var
last_cursor_pos = 0;
var
history_index;
var
this_fun, last_fun;
var
quote_flag =
false
;
var
utf8_state = 0;
var
utf8_val = 0;
var
term_fd;
var
term_read_buf;
var
term_width;
var
term_cursor_x = 0;
function
termInit() {
var
tab;
term_fd = std.
in
.fileno();
term_width = 80;
if
(os.isatty(term_fd)) {
if
(os.ttyGetWinSize) {
tab = os.ttyGetWinSize(term_fd);
if
(tab)
term_width = tab[0];
}
if
(os.ttySetRaw) {
os.ttySetRaw(term_fd);
}
}
os.signal(os.SIGINT, sigint_handler);
term_read_buf =
new
Uint8Array(64);
os.setReadHandler(term_fd, term_read_handler);
}
function
sigint_handler() {
handle_byte(3);
}
function
term_read_handler() {
var
l, i;
l = os.read(term_fd, term_read_buf.buffer, 0, term_read_buf.length);
for
(i = 0; i < l; i++)
handle_byte(term_read_buf[i]);
}
function
handle_byte(c) {
if
(!utf8) {
handle_char(c);
}
else
if
(utf8_state !== 0 && (c >= 0x80 && c < 0xc0)) {
utf8_val = (utf8_val << 6) | (c & 0x3F);
utf8_state--;
if
(utf8_state === 0) {
handle_char(utf8_val);
}
}
else
if
(c >= 0xc0 && c < 0xf8) {
utf8_state = 1 + (c >= 0xe0) + (c >= 0xf0);
utf8_val = c & ((1 << (6 - utf8_state)) - 1);
}
else
{
utf8_state = 0;
handle_char(c);
}
}
function
is_alpha(c) {
return
typeof
c ===
"string"
&&
((c >=
'A'
&& c <=
'Z'
) || (c >=
'a'
&& c <=
'z'
));
}
function
is_digit(c) {
return
typeof
c ===
"string"
&& (c >=
'0'
&& c <=
'9'
);
}
function
is_word(c) {
return
typeof
c ===
"string"
&&
(is_alpha(c) || is_digit(c) || c ==
'_'
|| c ==
'$'
);
}
function
ucs_length(str) {
var
len, c, i, str_len = str.length;
len = 0;
for
(i = 0; i < str_len; i++) {
c = str.charCodeAt(i);
if
(c < 0xdc00 || c >= 0xe000)
len++;
}
return
len;
}
function
is_trailing_surrogate(c) {
var
d;
if
(
typeof
c !==
"string"
)
return
false
;
d = c.codePointAt(0);
return
d >= 0xdc00 && d < 0xe000;
}
function
is_balanced(a, b) {
switch
(a + b) {
case
"()"
:
case
"[]"
:
case
"{}"
:
return
true
;
}
return
false
;
}
function
print_color_text(str, start, style_names) {
var
i, j;
for
(j = start; j < str.length;) {
var
style = style_names[i = j];
while
(++j < str.length && style_names[j] == style)
continue
;
std.puts(colors[styles[style] ||
'default'
]);
std.puts(str.substring(i, j));
std.puts(colors[
'none'
]);
}
}
function
print_csi(n, code) {
std.puts(
"\x1b["
+ ((n != 1) ? n :
""
) + code);
}
function
move_cursor(delta) {
var
i, l;
if
(delta > 0) {
while
(delta != 0) {
if
(term_cursor_x == (term_width - 1)) {
std.puts(
"\n"
);
term_cursor_x = 0;
delta--;
}
else
{
l = Math.min(term_width - 1 - term_cursor_x, delta);
print_csi(l,
"C"
);
delta -= l;
term_cursor_x += l;
}
}
}
else
{
delta = -delta;
while
(delta != 0) {
if
(term_cursor_x == 0) {
print_csi(1,
"A"
);
print_csi(term_width - 1,
"C"
);
delta--;
term_cursor_x = term_width - 1;
}
else
{
l = Math.min(delta, term_cursor_x);
print_csi(l,
"D"
);
delta -= l;
term_cursor_x -= l;
}
}
}
}
function
update() {
var
i, cmd_len;
if
(cmd != last_cmd) {
if
(!show_colors && last_cmd.substring(0, last_cursor_pos) == cmd.substring(0, last_cursor_pos)) {
std.puts(cmd.substring(last_cursor_pos));
}
else
{
move_cursor(-ucs_length(last_cmd.substring(0, last_cursor_pos)));
if
(show_colors) {
var
str = mexpr ? mexpr +
'\n'
+ cmd : cmd;
var
start = str.length - cmd.length;
var
colorstate = colorize_js(str);
print_color_text(str, start, colorstate[2]);
}
else
{
std.puts(cmd);
}
}
term_cursor_x = (term_cursor_x + ucs_length(cmd)) % term_width;
if
(term_cursor_x == 0) {
std.puts(
" \x08"
);
}
std.puts(
"\x1b[J"
);
last_cmd = cmd;
last_cursor_pos = cmd.length;
}
if
(cursor_pos > last_cursor_pos) {
move_cursor(ucs_length(cmd.substring(last_cursor_pos, cursor_pos)));
}
else
if
(cursor_pos < last_cursor_pos) {
move_cursor(-ucs_length(cmd.substring(cursor_pos, last_cursor_pos)));
}
last_cursor_pos = cursor_pos;
std.out.flush();
}
function
insert(str) {
if
(str) {
cmd = cmd.substring(0, cursor_pos) + str + cmd.substring(cursor_pos);
cursor_pos += str.length;
}
}
function
quoted_insert() {
quote_flag =
true
;
}
function
abort() {
cmd =
""
;
cursor_pos = 0;
return
-2;
}
function
alert() {
}
function
beginning_of_line() {
cursor_pos = 0;
}
function
end_of_line() {
cursor_pos = cmd.length;
}
function
forward_char() {
if
(cursor_pos < cmd.length) {
cursor_pos++;
while
(is_trailing_surrogate(cmd.charAt(cursor_pos)))
cursor_pos++;
}
}
function
backward_char() {
if
(cursor_pos > 0) {
cursor_pos--;
while
(is_trailing_surrogate(cmd.charAt(cursor_pos)))
cursor_pos--;
}
}
function
skip_word_forward(pos) {
while
(pos < cmd.length && !is_word(cmd.charAt(pos)))
pos++;
while
(pos < cmd.length && is_word(cmd.charAt(pos)))
pos++;
return
pos;
}
function
skip_word_backward(pos) {
while
(pos > 0 && !is_word(cmd.charAt(pos - 1)))
pos--;
while
(pos > 0 && is_word(cmd.charAt(pos - 1)))
pos--;
return
pos;
}
function
forward_word() {
cursor_pos = skip_word_forward(cursor_pos);
}
function
backward_word() {
cursor_pos = skip_word_backward(cursor_pos);
}
function
accept_line() {
std.puts(
"\n"
);
history_add(cmd);
return
-1;
}
function
history_add(str) {
if
(str) {
history.push(str);
}
history_index = history.length;
}
function
previous_history() {
if
(history_index > 0) {
if
(history_index == history.length) {
history.push(cmd);
}
history_index--;
cmd = history[history_index];
cursor_pos = cmd.length;
}
}
function
next_history() {
if
(history_index < history.length - 1) {
history_index++;
cmd = history[history_index];
cursor_pos = cmd.length;
}
}
function
history_search(dir) {
var
pos = cursor_pos;
for
(
var
i = 1; i <= history.length; i++) {
var
index = (history.length + i * dir + history_index) % history.length;
if
(history[index].substring(0, pos) == cmd.substring(0, pos)) {
history_index = index;
cmd = history[index];
return
;
}
}
}
function
history_search_backward() {
return
history_search(-1);
}
function
history_search_forward() {
return
history_search(1);
}
function
delete_char_dir(dir) {
var
start, end;
start = cursor_pos;
if
(dir < 0) {
start--;
while
(is_trailing_surrogate(cmd.charAt(start)))
start--;
}
end = start + 1;
while
(is_trailing_surrogate(cmd.charAt(end)))
end++;
if
(start >= 0 && start < cmd.length) {
if
(last_fun === kill_region) {
kill_region(start, end, dir);
}
else
{
cmd = cmd.substring(0, start) + cmd.substring(end);
cursor_pos = start;
}
}
}
function
delete_char() {
delete_char_dir(1);
}
function
control_d() {
if
(cmd.length == 0) {
std.puts(
"\n"
);
return
-3;
}
else
{
delete_char_dir(1);
}
}
function
backward_delete_char() {
delete_char_dir(-1);
}
function
transpose_chars() {
var
pos = cursor_pos;
if
(cmd.length > 1 && pos > 0) {
if
(pos == cmd.length)
pos--;
cmd = cmd.substring(0, pos - 1) + cmd.substring(pos, pos + 1) +
cmd.substring(pos - 1, pos) + cmd.substring(pos + 1);
cursor_pos = pos + 1;
}
}
function
transpose_words() {
var
p1 = skip_word_backward(cursor_pos);
var
p2 = skip_word_forward(p1);
var
p4 = skip_word_forward(cursor_pos);
var
p3 = skip_word_backward(p4);
if
(p1 < p2 && p2 <= cursor_pos && cursor_pos <= p3 && p3 < p4) {
cmd = cmd.substring(0, p1) + cmd.substring(p3, p4) +
cmd.substring(p2, p3) + cmd.substring(p1, p2);
cursor_pos = p4;
}
}
function
upcase_word() {
var
end = skip_word_forward(cursor_pos);
cmd = cmd.substring(0, cursor_pos) +
cmd.substring(cursor_pos, end).toUpperCase() +
cmd.substring(end);
}
function
downcase_word() {
var
end = skip_word_forward(cursor_pos);
cmd = cmd.substring(0, cursor_pos) +
cmd.substring(cursor_pos, end).toLowerCase() +
cmd.substring(end);
}
function
kill_region(start, end, dir) {
var
s = cmd.substring(start, end);
if
(last_fun !== kill_region)
clip_board = s;
else
if
(dir < 0)
clip_board = s + clip_board;
else
clip_board = clip_board + s;
cmd = cmd.substring(0, start) + cmd.substring(end);
if
(cursor_pos > end)
cursor_pos -= end - start;
else
if
(cursor_pos > start)
cursor_pos = start;
this_fun = kill_region;
}
function
kill_line() {
kill_region(cursor_pos, cmd.length, 1);
}
function
backward_kill_line() {
kill_region(0, cursor_pos, -1);
}
function
kill_word() {
kill_region(cursor_pos, skip_word_forward(cursor_pos), 1);
}
function
backward_kill_word() {
kill_region(skip_word_backward(cursor_pos), cursor_pos, -1);
}
function
yank() {
insert(clip_board);
}
function
control_c() {
if
(last_fun === control_c) {
std.puts(
"\n"
);
std.exit(0);
}
else
{
std.puts(
"\n(Press Ctrl-C again to quit)\n"
);
readline_print_prompt();
}
}
function
reset() {
cmd =
""
;
cursor_pos = 0;
}
function
get_context_word(line, pos) {
var
s =
""
;
while
(pos > 0 && is_word(line[pos - 1])) {
pos--;
s = line[pos] + s;
}
return
s;
}
function
get_context_object(line, pos) {
var
obj, base, c;
if
(pos <= 0 ||
" ~!%^&*(-+={[|:;,<>?/"
.indexOf(line[pos - 1]) >= 0)
return
g;
if
(pos >= 2 && line[pos - 1] ===
"."
) {
pos--;
obj = {};
switch
(c = line[pos - 1]) {
case
'\''
:
case
'\"'
:
return
"a
";
case ']':
return [];
case '}':
return {};
case '/':
return / /;
default:
if (is_word(c)) {
base = get_context_word(line, pos);
if (["
true
", "
false
", "
null
", "
this
"].includes(base) || !isNaN(+base))
return eval(base);
obj = get_context_object(line, pos - base.length);
if (obj === null || obj === void 0)
return obj;
if (obj === g && obj[base] === void 0)
return eval(base);
else
return obj[base];
}
return {};
}
}
return void 0;
}
function get_completions(line, pos) {
var s, obj, ctx_obj, r, i, j, paren;
s = get_context_word(line, pos);
ctx_obj = get_context_object(line, pos - s.length);
r = [];
/* enumerate properties from object and its prototype chain,
add non-numeric regular properties with s as e prefix
*/
for (i = 0, obj = ctx_obj; i < 10 && obj !== null && obj !== void 0; i++) {
var props = Object.getOwnPropertyNames(obj);
/* add non-numeric regular properties */
for (j = 0; j < props.length; j++) {
var prop = props[j];
if (typeof prop == "
string
" && "
"+(+prop) != prop && prop.startsWith(s))
r.push(prop);
}
obj = Object.getPrototypeOf(obj);
}
if (r.length > 1) {
/* sort list with internal names last and remove duplicates */
function symcmp(a, b) {
if (a[0] != b[0]) {
if (a[0] == '_')
return 1;
if (b[0] == '_')
return -1;
}
if (a < b)
return -1;
if (a > b)
return +1;
return 0;
}
r.sort(symcmp);
for(i = j = 1; i < r.length; i++) {
if (r[i] != r[i - 1])
r[j++] = r[i];
}
r.length = j;
}
/* 'tab' = list of completions, 'pos' = cursor position inside
the completions */
return { tab: r, pos: s.length, ctx: ctx_obj };
}
function completion() {
var tab, res, s, i, j, len, t, max_width, col, n_cols, row, n_rows;
res = get_completions(cmd, cursor_pos);
tab = res.tab;
if (tab.length === 0)
return;
s = tab[0];
len = s.length;
/* add the chars which are identical in all the completions */
for(i = 1; i < tab.length; i++) {
t = tab[i];
for(j = 0; j < len; j++) {
if (t[j] !== s[j]) {
len = j;
break;
}
}
}
for(i = res.pos; i < len; i++) {
insert(s[i]);
}
if (last_fun === completion && tab.length == 1) {
/* append parentheses to function names */
var m = res.ctx[tab[0]];
if (typeof m == "
function
") {
insert('(');
if (m.length == 0)
insert(')');
} else if (typeof m == "
object
") {
insert('.');
}
}
/* show the possible completions */
if (last_fun === completion && tab.length >= 2) {
max_width = 0;
for(i = 0; i < tab.length; i++)
max_width = Math.max(max_width, tab[i].length);
max_width += 2;
n_cols = Math.max(1, Math.floor((term_width + 1) / max_width));
n_rows = Math.ceil(tab.length / n_cols);
std.puts("
\n
");
/* display the sorted list column-wise */
for (row = 0; row < n_rows; row++) {
for (col = 0; col < n_cols; col++) {
i = col * n_rows + row;
if (i >= tab.length)
break;
s = tab[i];
if (col != n_cols - 1)
s = s.padEnd(max_width);
std.puts(s);
}
std.puts("
\n
");
}
/* show a new prompt */
readline_print_prompt();
}
}
var commands = { /* command table */
"
\x01
": beginning_of_line, /* ^A - bol */
"
\x02
": backward_char, /* ^B - backward-char */
"
\x03
": control_c, /* ^C - abort */
"
\x04
": control_d, /* ^D - delete-char or exit */
"
\x05
": end_of_line, /* ^E - eol */
"
\x06
": forward_char, /* ^F - forward-char */
"
\x07
": abort, /* ^G - bell */
"
\x08
": backward_delete_char, /* ^H - backspace */
"
\x09
": completion, /* ^I - history-search-backward */
"
\x0a
": accept_line, /* ^J - newline */
"
\x0b
": kill_line, /* ^K - delete to end of line */
"
\x0d
": accept_line, /* ^M - enter */
"
\x0e
": next_history, /* ^N - down */
"
\x10
": previous_history, /* ^P - up */
"
\x11
": quoted_insert, /* ^Q - quoted-insert */
"
\x12
": alert, /* ^R - reverse-search */
"
\x13
": alert, /* ^S - search */
"
\x14
": transpose_chars, /* ^T - transpose */
"
\x18
": reset, /* ^X - cancel */
"
\x19
": yank, /* ^Y - yank */
"
\x1bOA
": previous_history, /* ^[OA - up */
"
\x1bOB
": next_history, /* ^[OB - down */
"
\x1bOC
": forward_char, /* ^[OC - right */
"
\x1bOD
": backward_char, /* ^[OD - left */
"
\x1bOF
": forward_word, /* ^[OF - ctrl-right */
"
\x1bOH
": backward_word, /* ^[OH - ctrl-left */
"
\x1b[1;5C
": forward_word, /* ^[[1;5C - ctrl-right */
"
\x1b[1;5D
": backward_word, /* ^[[1;5D - ctrl-left */
"
\x1b[1~
": beginning_of_line, /* ^[[1~ - bol */
"
\x1b[3~
": delete_char, /* ^[[3~ - delete */
"
\x1b[4~
": end_of_line, /* ^[[4~ - eol */
"
\x1b[5~
": history_search_backward,/* ^[[5~ - page up */
"
\x1b[6~
": history_search_forward, /* ^[[5~ - page down */
"
\x1b[A
": previous_history, /* ^[[A - up */
"
\x1b[B
": next_history, /* ^[[B - down */
"
\x1b[C
": forward_char, /* ^[[C - right */
"
\x1b[D
": backward_char, /* ^[[D - left */
"
\x1b[F
": end_of_line, /* ^[[F - end */
"
\x1b[H
": beginning_of_line, /* ^[[H - home */
"
\x1b\x7f
": backward_kill_word, /* M-C-? - backward_kill_word */
"
\x1bb
": backward_word, /* M-b - backward_word */
"
\x1bd
": kill_word, /* M-d - kill_word */
"
\x1bf
": forward_word, /* M-f - backward_word */
"
\x1bk
": backward_kill_line, /* M-k - backward_kill_line */
"
\x1bl
": downcase_word, /* M-l - downcase_word */
"
\x1bt
": transpose_words, /* M-t - transpose_words */
"
\x1bu
": upcase_word, /* M-u - upcase_word */
"
\x7f
": backward_delete_char, /* ^? - delete */
};
function dupstr(str, count) {
var res = "
";
while (count-- > 0)
res += str;
return res;
}
var readline_keys;
var readline_state;
var readline_cb;
function readline_print_prompt()
{
std.puts(prompt);
term_cursor_x = ucs_length(prompt) % term_width;
last_cmd = "
";
last_cursor_pos = 0;
}
function readline_start(defstr, cb) {
cmd = defstr || "
";
cursor_pos = cmd.length;
history_index = history.length;
readline_cb = cb;
prompt = pstate;
if (mexpr) {
prompt += dupstr("
", plen - prompt.length);
prompt += ps2;
} else {
if (show_time) {
var t = eval_time / 1000;
prompt += t.toFixed(6) + "
";
}
plen = prompt.length;
prompt += ps1;
}
readline_print_prompt();
update();
readline_state = 0;
}
function handle_char(c1) {
var c;
c = String.fromCodePoint(c1);
switch(readline_state) {
case 0:
if (c == '\x1b') { /* '^[' - ESC */
readline_keys = c;
readline_state = 1;
} else {
handle_key(c);
}
break;
case 1: /* '^[ */
readline_keys += c;
if (c == '[') {
readline_state = 2;
} else if (c == 'O') {
readline_state = 3;
} else {
handle_key(readline_keys);
readline_state = 0;
}
break;
case 2: /* '^[[' - CSI */
readline_keys += c;
if (!(c == ';' || (c >= '0' && c <= '9'))) {
handle_key(readline_keys);
readline_state = 0;
}
break;
case 3: /* '^[O' - ESC2 */
readline_keys += c;
handle_key(readline_keys);
readline_state = 0;
break;
}
}
function handle_key(keys) {
var fun;
if (quote_flag) {
if (ucs_length(keys) === 1)
insert(keys);
quote_flag = false;
} else if (fun = commands[keys]) {
this_fun = fun;
switch (fun(keys)) {
case -1:
readline_cb(cmd);
return;
case -2:
readline_cb(null);
return;
case -3:
/* uninstall a Ctrl-C signal handler */
os.signal(os.SIGINT, null);
/* uninstall the stdin read handler */
os.setReadHandler(term_fd, null);
return;
}
last_fun = this_fun;
} else if (ucs_length(keys) === 1 && keys >= ' ') {
insert(keys);
last_fun = insert;
} else {
alert(); /* beep! */
}
cursor_pos = (cursor_pos < 0) ? 0 :
(cursor_pos > cmd.length) ? cmd.length : cursor_pos;
update();
}
var hex_mode = false;
var eval_mode = "
std
";
function number_to_string(a, radix) {
var s;
if (!isFinite(a)) {
/* NaN, Infinite */
return a.toString();
} else {
if (a == 0) {
if (1 / a < 0)
s = "
-0
";
else
s = "
0
";
} else {
if (radix == 16 && a === Math.floor(a)) {
var s;
if (a < 0) {
a = -a;
s = "
-
";
} else {
s = "
";
}
s += "
0x
" + a.toString(16);
} else {
s = a.toString();
}
}
return s;
}
}
function bigfloat_to_string(a, radix) {
var s;
if (!BigFloat.isFinite(a)) {
/* NaN, Infinite */
if (eval_mode !== "
math
") {
return "
BigFloat(
" + a.toString() + "
)
";
} else {
return a.toString();
}
} else {
if (a == 0) {
if (1 / a < 0)
s = "
-0
";
else
s = "
0
";
} else {
if (radix == 16) {
var s;
if (a < 0) {
a = -a;
s = "
-
";
} else {
s = "
";
}
s += "
0x
" + a.toString(16);
} else {
s = a.toString();
}
}
if (typeof a === "
bigfloat
" && eval_mode !== "
math
") {
s += "
l
";
} else if (eval_mode !== "
std
" && s.indexOf("
.
") < 0 &&
((radix == 16 && s.indexOf("
p
") < 0) ||
(radix == 10 && s.indexOf("
e
") < 0))) {
/* add a decimal point so that the floating point type
is visible */
s += "
.0
";
}
return s;
}
}
function bigint_to_string(a, radix) {
var s;
if (radix == 16) {
var s;
if (a < 0) {
a = -a;
s = "
-
";
} else {
s = "
";
}
s += "
0x
" + a.toString(16);
} else {
s = a.toString();
}
if (eval_mode === "
std
")
s += "
n
";
return s;
}
function print(a) {
var stack = [];
function print_rec(a) {
var n, i, keys, key, type, s;
type = typeof(a);
if (type === "
object
") {
if (a === null) {
std.puts(a);
} else if (stack.indexOf(a) >= 0) {
std.puts("
[circular]
");
} else if (has_jscalc && (a instanceof Fraction ||
a instanceof Complex ||
a instanceof Mod ||
a instanceof Polynomial ||
a instanceof PolyMod ||
a instanceof RationalFunction ||
a instanceof Series)) {
std.puts(a.toString());
} else {
stack.push(a);
if (Array.isArray(a)) {
n = a.length;
std.puts("
[
");
for(i = 0; i < n; i++) {
if (i !== 0)
std.puts("
,
");
if (i in a) {
print_rec(a[i]);
} else {
std.puts("
<empty>
");
}
if (i > 20) {
std.puts("
...
");
break;
}
}
std.puts("
]
");
} else if (Object.__getClass(a) === "
RegExp
") {
std.puts(a.toString());
} else {
keys = Object.keys(a);
n = keys.length;
std.puts("
{
");
for(i = 0; i < n; i++) {
if (i !== 0)
std.puts("
,
");
key = keys[i];
std.puts(key, "
:
");
print_rec(a[key]);
}
std.puts("
}
");
}
stack.pop(a);
}
} else if (type === "
string
") {
s = a.__quote();
if (s.length > 79)
s = s.substring(0, 75) + "
...\
""
;
std.puts(s);
}
else
if
(type ===
"number"
) {
std.puts(number_to_string(a, hex_mode ? 16 : 10));
}
else
if
(type ===
"bigint"
) {
std.puts(bigint_to_string(a, hex_mode ? 16 : 10));
}
else
if
(type ===
"bigfloat"
) {
std.puts(bigfloat_to_string(a, hex_mode ? 16 : 10));
}
else
if
(type ===
"bigdecimal"
) {
std.puts(a.toString() +
"m"
);
}
else
if
(type ===
"symbol"
) {
std.puts(String(a));
}
else
if
(type ===
"function"
) {
std.puts(
"function "
+ a.name +
"()"
);
}
else
{
std.puts(a);
}
}
print_rec(a);
}
function
extract_directive(a) {
var
pos;
if
(a[0] !== '\\
')
return "";
for (pos = 1; pos < a.length; pos++) {
if (!is_alpha(a[pos]))
break;
}
return a.substring(1, pos);
}
/* return true if the string after cmd can be evaluted as JS */
function handle_directive(cmd, expr) {
var param, prec1, expBits1;
if (cmd === "h" || cmd === "?" || cmd == "help") {
help();
} else if (cmd === "load") {
var filename = expr.substring(cmd.length + 1).trim();
if (filename.lastIndexOf(".") <= filename.lastIndexOf("/"))
filename += ".js";
std.loadScript(filename);
return false;
} else if (cmd === "x") {
hex_mode = true;
} else if (cmd === "d") {
hex_mode = false;
} else if (cmd === "t") {
show_time = !show_time;
} else if (has_bignum && cmd === "p") {
param = expr.substring(cmd.length + 1).trim().split(" ");
if (param.length === 1 && param[0] === "") {
std.puts("BigFloat precision=" + prec + " bits (~" +
Math.floor(prec / log2_10) +
" digits), exponent size=" + expBits + " bits\n");
} else if (param[0] === "f16") {
prec = 11;
expBits = 5;
} else if (param[0] === "f32") {
prec = 24;
expBits = 8;
} else if (param[0] === "f64") {
prec = 53;
expBits = 11;
} else if (param[0] === "f128") {
prec = 113;
expBits = 15;
} else {
prec1 = parseInt(param[0]);
if (param.length >= 2)
expBits1 = parseInt(param[1]);
else
expBits1 = BigFloatEnv.expBitsMax;
if (Number.isNaN(prec1) ||
prec1 < BigFloatEnv.precMin ||
prec1 > BigFloatEnv.precMax) {
std.puts("Invalid precision\n");
return false;
}
if (Number.isNaN(expBits1) ||
expBits1 < BigFloatEnv.expBitsMin ||
expBits1 > BigFloatEnv.expBitsMax) {
std.puts("Invalid exponent bits\n");
return false;
}
prec = prec1;
expBits = expBits1;
}
return false;
} else if (has_bignum && cmd === "digits") {
param = expr.substring(cmd.length + 1).trim();
prec1 = Math.ceil(parseFloat(param) * log2_10);
if (prec1 < BigFloatEnv.precMin ||
prec1 > BigFloatEnv.precMax) {
std.puts("Invalid precision\n");
return false;
}
prec = prec1;
expBits = BigFloatEnv.expBitsMax;
return false;
} else if (has_bignum && cmd === "mode") {
param = expr.substring(cmd.length + 1).trim();
if (param === "") {
std.puts("Running mode=" + eval_mode + "\n");
} else if (param === "std" || param === "math") {
eval_mode = param;
} else {
std.puts("Invalid mode\n");
}
return false;
} else if (cmd === "clear") {
std.puts("\x1b[H\x1b[J");
} else if (cmd === "q") {
std.exit(0);
} else if (has_jscalc && cmd === "a") {
algebraicMode = true;
} else if (has_jscalc && cmd === "n") {
algebraicMode = false;
} else {
std.puts("Unknown directive: " + cmd + "\n");
return false;
}
return true;
}
if (config_numcalc) {
/* called by the GUI */
g.execCmd = function (cmd) {
switch(cmd) {
case "dec":
hex_mode = false;
break;
case "hex":
hex_mode = true;
break;
case "num":
algebraicMode = false;
break;
case "alg":
algebraicMode = true;
break;
}
}
}
function help() {
function sel(n) {
return n ? "*": " ";
}
std.puts("\\h this help\n" +
"\\x " + sel(hex_mode) + "hexadecimal number display\n" +
"\\d " + sel(!hex_mode) + "decimal number display\n" +
"\\t " + sel(show_time) + "toggle timing display\n" +
"\\clear clear the terminal\n");
if (has_jscalc) {
std.puts("\\a " + sel(algebraicMode) + "algebraic mode\n" +
"\\n " + sel(!algebraicMode) + "numeric mode\n");
}
if (has_bignum) {
std.puts("\\p [m [e]] set the BigFloat precision to '
m
' bits\n" +
"\\digits n set the BigFloat precision to '
ceil(n*log2(10))
' bits\n");
if (!has_jscalc) {
std.puts("\\mode [std|math] change the running mode (current = " + eval_mode + ")\n");
}
}
if (!config_numcalc) {
std.puts("\\q exit\n");
}
}
function cmd_start() {
if (!config_numcalc) {
if (has_jscalc)
std.puts('
QJSCalc - Type
"\\h"
for
help\n
');
else
std.puts('
QuickJS - Type
"\\h"
for
help\n
');
}
if (has_bignum) {
log2_10 = Math.log(10) / Math.log(2);
prec = 113;
expBits = 15;
if (has_jscalc) {
eval_mode = "math";
/* XXX: numeric mode should always be the default ? */
g.algebraicMode = config_numcalc;
}
}
cmd_readline_start();
}
function cmd_readline_start() {
readline_start(dupstr(" ", level), readline_handle_cmd);
}
function readline_handle_cmd(expr) {
if (!handle_cmd(expr)) {
cmd_readline_start();
}
}
/* return true if async termination */
function handle_cmd(expr) {
var colorstate, cmd;
if (expr === null) {
expr = "";
return false;
}
if (expr === "?") {
help();
return false;
}
cmd = extract_directive(expr);
if (cmd.length > 0) {
if (!handle_directive(cmd, expr)) {
return false;
}
expr = expr.substring(cmd.length + 1);
}
if (expr === "")
return false;
if (mexpr)
expr = mexpr + '
\n
' + expr;
colorstate = colorize_js(expr);
pstate = colorstate[0];
level = colorstate[1];
if (pstate) {
mexpr = expr;
return false;
}
mexpr = "";
if (has_bignum) {
/* XXX: async is not supported in this case */
BigFloatEnv.setPrec(eval_and_print_start.bind(null, expr, false),
prec, expBits);
} else {
eval_and_print_start(expr, true);
}
return true;
}
function eval_and_print_start(expr, is_async) {
var result;
try {
if (eval_mode === "math")
expr = '
"use math"
; void 0;
' + expr;
eval_start_time = os.now();
/* eval as a script */
result = std.evalScript(expr, { backtrace_barrier: true, async: is_async });
if (is_async) {
/* result is a promise */
result.then(print_eval_result, print_eval_error);
} else {
print_eval_result(result);
}
} catch (error) {
print_eval_error(error);
}
}
function print_eval_result(result) {
eval_time = os.now() - eval_start_time;
std.puts(colors[styles.result]);
print(result);
std.puts("\n");
std.puts(colors.none);
/* set the last result */
g._ = result;
handle_cmd_end();
}
function print_eval_error(error) {
std.puts(colors[styles.error_msg]);
if (error instanceof Error) {
console.log(error);
if (error.stack) {
std.puts(error.stack);
}
} else {
std.puts("Throw: ");
console.log(error);
}
std.puts(colors.none);
handle_cmd_end();
}
function handle_cmd_end() {
level = 0;
/* run the garbage collector after each command */
std.gc();
cmd_readline_start();
}
function colorize_js(str) {
var i, c, start, n = str.length;
var style, state = "", level = 0;
var primary, can_regex = 1;
var r = [];
function push_state(c) { state += c; }
function last_state(c) { return state.substring(state.length - 1); }
function pop_state(c) {
var c = last_state();
state = state.substring(0, state.length - 1);
return c;
}
function parse_block_comment() {
style = '
comment
';
push_state('
/
');
for (i++; i < n - 1; i++) {
if (str[i] == '
*
' && str[i + 1] == '
/
') {
i += 2;
pop_state('
/
');
break;
}
}
}
function parse_line_comment() {
style = '
comment
';
for (i++; i < n; i++) {
if (str[i] == '
\n
') {
break;
}
}
}
function parse_string(delim) {
style = '
string
';
push_state(delim);
while (i < n) {
c = str[i++];
if (c == '
\n
') {
style = '
error
';
continue;
}
if (c == '
\\
') {
if (i >= n)
break;
i++;
} else
if (c == delim) {
pop_state();
break;
}
}
}
function parse_regex() {
style = '
regex
';
push_state('
/
');
while (i < n) {
c = str[i++];
if (c == '
\n
') {
style = '
error
';
continue;
}
if (c == '
\\
') {
if (i < n) {
i++;
}
continue;
}
if (last_state() == '
[
') {
if (c == '
]
') {
pop_state()
}
// ECMA 5: ignore '
/
' inside char classes
continue;
}
if (c == '
[
') {
push_state('
[
');
if (str[i] == '
[
' || str[i] == '
]
')
i++;
continue;
}
if (c == '
/
') {
pop_state();
while (i < n && is_word(str[i]))
i++;
break;
}
}
}
function parse_number() {
style = '
number
';
while (i < n && (is_word(str[i]) || (str[i] == '
.
' && (i == n - 1 || str[i + 1] != '
.
')))) {
i++;
}
}
var js_keywords = "|" +
"break|case|catch|continue|debugger|default|delete|do|" +
"else|finally|for|function|if|in|instanceof|new|" +
"return|switch|this|throw|try|typeof|while|with|" +
"class|const|enum|import|export|extends|super|" +
"implements|interface|let|package|private|protected|" +
"public|static|yield|" +
"undefined|null|true|false|Infinity|NaN|" +
"eval|arguments|" +
"await|";
var js_no_regex = "|this|super|undefined|null|true|false|Infinity|NaN|arguments|";
var js_types = "|void|var|";
function parse_identifier() {
can_regex = 1;
while (i < n && is_word(str[i]))
i++;
var w = '
|
' + str.substring(start, i) + '
|
';
if (js_keywords.indexOf(w) >= 0) {
style = '
keyword
';
if (js_no_regex.indexOf(w) >= 0)
can_regex = 0;
return;
}
var i1 = i;
while (i1 < n && str[i1] == '
')
i1++;
if (i1 < n && str[i1] == '
(
') {
style = '
function
';
return;
}
if (js_types.indexOf(w) >= 0) {
style = '
type
';
return;
}
style = '
identifier
';
can_regex = 0;
}
function set_style(from, to) {
while (r.length < from)
r.push('
default
');
while (r.length < to)
r.push(style);
}
for (i = 0; i < n;) {
style = null;
start = i;
switch (c = str[i++]) {
case '
':
case '
\t
':
case '
\r
':
case '
\n
':
continue;
case '
+
':
case '
-
':
if (i < n && str[i] == c) {
i++;
continue;
}
can_regex = 1;
continue;
case '
/
':
if (i < n && str[i] == '
*
') { // block comment
parse_block_comment();
break;
}
if (i < n && str[i] == '
/
') { // line comment
parse_line_comment();
break;
}
if (can_regex) {
parse_regex();
can_regex = 0;
break;
}
can_regex = 1;
continue;
case '
\
''
:
case
'\"'
:
case
'`'
:
parse_string(c);
can_regex = 0;
break
;
case
'('
:
case
'['
:
case
'{'
:
can_regex = 1;
level++;
push_state(c);
continue
;
case
')'
:
case
']'
:
case
'}'
:
can_regex = 0;
if
(level > 0 && is_balanced(last_state(), c)) {
level--;
pop_state();
continue
;
}
style =
'error'
;
break
;
default
:
if
(is_digit(c)) {
parse_number();
can_regex = 0;
break
;
}
if
(is_word(c) || c ==
'$'
) {
parse_identifier();
break
;
}
can_regex = 1;
continue
;
}
if
(style)
set_style(start, i);
}
set_style(n, n);
return
[ state, level, r ];
}
termInit();
cmd_start();
})(globalThis);