Author Topic: Script BASIC JavaScript Extension Module (Linux)  (Read 35199 times)

Support

  • Administrator
  • *****
  • Posts: 1
    • View Profile
Script BASIC JavaScript Extension Module (Linux)
« on: October 19, 2017, 05:25:25 am »
The Script BASIC JS extension module for Linux is based on the Cesanta's V7 JavaScript Engine. It claims to be the world's smallest footprint JavaScript 5.1 compatible embeddable engine. There are no other dependencies required.

JavaScript Programmers Guide

V7 JavaScript Documentation

Features:
  • Dynamically create JavaScript code in Script BASIC and execute the script.,
  • Call JavaScript functions and access variables from Script BASIC
  • Create / change JavaScript object properties and methods from Script BASIC
  • and much more ...

Note: The \ character is used by Script BASIC as a string escape character and must be inserted in the JavaScript code to make the \ just text. Loading JavaScript code from a file doesn't have the escape character issue and can be run verbatim.

js.inc
MODULE JS

' CORE
DECLARE SUB      js_create                  ALIAS "js_create"                 LIB "js"
DECLARE SUB      js_destroy                 ALIAS "js_destroy"                LIB "js"
DECLARE SUB      js_get_global              ALIAS "js_get_global"             LIB "js"
DECLARE SUB      js_get_this                ALIAS "js_get_this"               LIB "js"
DECLARE SUB      js_get_arguments           ALIAS "js_get_arguments"          LIB "js"
DECLARE SUB      js_arg                     ALIAS "js_arg"                    LIB "js"
DECLARE SUB      js_argc                    ALIAS "js_argc"                   LIB "js"
DECLARE SUB      js_own                     ALIAS "js_own"                    LIB "js"
DECLARE SUB      js_disown                  ALIAS "js_disown"                 LIB "js"
DECLARE SUB      js_set_gc_enabled          ALIAS "js_set_gc_enabled"         LIB "js"
DECLARE SUB      js_interrupt               ALIAS "js_interrupt"              LIB "js"
DECLARE SUB      js_get_parser_error        ALIAS "js_get_parser_error"       LIB "js"

' PRIMITIVES
DECLARE SUB      js_mk_number               ALIAS "js_mk_number"              LIB "js"
DECLARE SUB      js_get_double              ALIAS "js_get_double"             LIB "js"
DECLARE SUB      js_get_int                 ALIAS "js_get_int"                LIB "js"
DECLARE SUB      js_is_number               ALIAS "js_is_number"              LIB "js"
DECLARE SUB      js_mk_boolean              ALIAS "js_mk_boolean"             LIB "js"
DECLARE SUB      js_get_bool                ALIAS "js_get_bool"               LIB "js"
DECLARE SUB      js_is_boolean              ALIAS "js_is_boolean"             LIB "js"
DECLARE SUB      js_mk_null                 ALIAS "js_mk_null"                LIB "js"
DECLARE SUB      js_is_null                 ALIAS "js_is_null"                LIB "js"
DECLARE SUB      js_mk_undefined            ALIAS "js_mk_undefined"           LIB "js"
DECLARE SUB      js_is_undefined            ALIAS "js_is_undefined"           LIB "js"
DECLARE SUB      js_mk_foreign              ALIAS "js_mk_foreign"             LIB "js"
DECLARE SUB      js_get_ptr                 ALIAS "js_get_ptr"                LIB "js"
DECLARE SUB      js_is_foreign              ALIAS "js_is_foreign"             LIB "js"

' STRINGS
DECLARE SUB      js_mk_string               ALIAS "js_mk_string"              LIB "js"
DECLARE SUB      js_is_string               ALIAS "js_is_string"              LIB "js"
DECLARE SUB      js_get_string              ALIAS "js_get_string"             LIB "js"
DECLARE SUB      js_get_cstring             ALIAS "js_get_cstring"            LIB "js"

' OBJECTS
DECLARE SUB      js_mk_object               ALIAS "js_mk_object"              LIB "js"
DECLARE SUB      js_is_object               ALIAS "js_is_object"              LIB "js"
DECLARE SUB      js_get_proto               ALIAS "js_get_proto"              LIB "js"
DECLARE SUB      js_set_proto               ALIAS "js_set_proto"              LIB "js"
DECLARE SUB      js_get                     ALIAS "js_get"                    LIB "js"
DECLARE SUB      js_def                     ALIAS "js_def"                    LIB "js"
DECLARE SUB      js_set                     ALIAS "js_set"                    LIB "js"
DECLARE SUB      js_del                     ALIAS "js_del"                    LIB "js"
DECLARE SUB      js_init_prop_iter_ctx      ALIAS "js_init_prop_iter_ctx"     LIB "js"
DECLARE SUB      js_next_prop               ALIAS "js_next_prop"              LIB "js"
DECLARE SUB      js_destruct_prop_iter_ctx  ALIAS "js_destruct_prop_iter_ctx" LIB "js"
DECLARE SUB      js_is_instanceof           ALIAS "js_is_instanceof"          LIB "js"
DECLARE SUB      js_is_instanceof_v         ALIAS "js_is_instanceof_v"        LIB "js"

' ARRAYS
DECLARE SUB      js_mk_array                ALIAS "js_mk_array"               LIB "js"
DECLARE SUB      js_is_array                ALIAS "js_is_array"               LIB "js"
DECLARE SUB      js_array_length            ALIAS "js_array_length"           LIB "js"
DECLARE SUB      js_array_push              ALIAS "js_array_push"             LIB "js"
DECLARE SUB      js_array_get               ALIAS "js_array_get"              LIB "js"
DECLARE SUB      js_array_set               ALIAS "js_array_set"              LIB "js"
DECLARE SUB      js_array_del               ALIAS "js_array_del"              LIB "js"

' EXECUTION
DECLARE SUB      js_exec                    ALIAS "js_exec"                   LIB "js"
DECLARE SUB      js_exec_file               ALIAS "js_exec_file"              LIB "js"
DECLARE SUB      js_apply                   ALIAS "js_apply"                  LIB "js"
DECLARE SUB      js_parse_json              ALIAS "js_parse_json"             LIB "js"
DECLARE SUB      js_parse_json_file         ALIAS "js_parse_json_file"        LIB "js"

'REGEX
DECLARE SUB      js_mk_regexp               ALIAS "js_mk_regexp"              LIB "js"
DECLARE SUB      js_is_regexp               ALIAS "js_is_regexp"              LIB "js"

' UTILITY
DECLARE SUB      js_stringify               ALIAS "js_stringify"              LIB "js"
DECLARE SUB      js_println                 ALIAS "js_println"                LIB "js"

DECLARE SUB      SB_shifts                  ALIAS "SB_shifts"                 LIB "js"
DECLARE COMMAND  js_iif                     ALIAS "js_iif"                    LIB "js"


' JS Global Module Variables
OBJ = 0
SYS = 0

' Stringify Modes
DEFAULT = 0
JSON    = 1
DEBUG   = 2

' Property Attribute Support

CONST V7_PROPERTY_NON_WRITABLE              = 1
CONST V7_PROPERTY_NON_ENUMERABLE            = 2
CONST V7_PROPERTY_NON_CONFIGURABLE          = 4
CONST V7_PROPERTY_GETTER                    = 8
CONST V7_PROPERTY_SETTER                    = 16
CONST _V7_PROPERTY_HIDDEN                   = 32
CONST _V7_PROPERTY_OFF_HEAP                 = 64
CONST _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR = 128
CONST _V7_DESC_PRESERVE_VALUE               = 256
CONST _V7_DESC_MASK                         = &HFFFF

CONST PROPERTY_DEFAULT = 0

' TRUE or FALSE. Whether the property's value can be set.
FUNCTION WRITABLE(v)
  IF v THEN
    WRITABLE = PROPERTY_DEFAULT
  ELSE
    WRITABLE = V7_PROPERTY_NON_WRITABLE
  END IF
END FUNCTION

' TRUE or FALSE. Whether the property shows in some loop constructs.
FUNCTION ENUMERABLE(v)
  IF v THEN
    ENUMERABLE = PROPERTY_DEFAULT
  ELSE
    ENUMERABLE = V7_PROPERTY_NON_ENUMERABLE
  END IF
END FUNCTION

' TRUE or FALSE. Whether the property can be deleted and whether its attributes can be changed.
FUNCTION CONFIGURABLE(v)
  IF v THEN
    CONFIGURABLE = PROPERTY_DEFAULT
  ELSE
    CONFIGURABLE = V7_PROPERTY_NON_CONFIGURABLE
  END IF
END FUNCTION

' TRUE or FALSE. When a property is accessed the value is generated by calling a function implicitly.
FUNCTION GETTER(v)
  IF v THEN
    GETTER = V7_PROPERTY_GETTER
  ELSE
    GETTER = FALSE
  END IF
END FUNCTION

' TRUE or FALSE. When a property is set it will implicitly call a function and pass a
' value as argument, and the return value of the function is set to the property.
FUNCTION SETTER(v)
  IF v THEN
    SETTER = V7_PROPERTY_SETTER
  ELSE
    SETTER = FALSE
  END IF
END FUNCTION

FUNCTION PRESERVE_VALUE
    PRESERVE_VALUE = _V7_DESC_PRESERVE_VALUE
END FUNCTION

FUNCTION HIDDEN(v)
  IF v THEN
    HIDDEN = V7_PROPERTY_HIDDEN
  ELSE
    HIDDEN = FALSE
  END IF
END FUNCTION

FUNCTION OFF_HEAP(v)
  IF v THEN
    OFF_HEAP = _V7_PROPERTY_OFF_HEAP
  ELSE
    OFF_HEAP = FALSE
  END IF
END FUNCTION


' JS API Function Wrappers

' Create V7 instance
FUNCTION CREATE
  OBJ = js_create()
  SYS = js_get_global(OBJ)
  CREATE = OBJ
END FUNCTION

' Destroy V7 instance
SUB DESTROY
  js_destroy(OBJ)
  UNDEF OBJ
END SUB

' Return root level (`global`) object of the given V7 instance
FUNCTION GET_GLOBAL
  GET_GLOBAL = js_get_global(OBJ)
END FUNCTION

' Return current `this` object
FUNCTION GET_THIS
  GET_THIS = js_get_this(OBJ)
END FUNCTION

' Return current `arguments` array
FUNCTION GET_ARGUMENTS
  GET_ARGUMENTS = js_get_arguments(OBJ)
END FUNCTION

' Return i-th argument
FUNCTION ARG(i)
  ARG = js_arg(OBJ, i)
END FUNCTION

' Return the length (`count`) of `arguments`
FUNCTION ARGC
  ARGC = js_argc(OBJ)
END FUNCTION

' Tells the GC about a JS value variable/field owned by `C` code.
SUB OWN(v)
  js_own(OBJ, v)
END SUB

' User code should also explicitly disown the variables with v7_disown
' once it goes out of scope or the structure containing the v7_val_t field is freed.
' Returns 1 if value is found, 0 otherwise
FUNCTION DISOWN(v)
  DISOWN = js_disown(OBJ, v)
END FUNCTION

' Enable or disable GC
SUB SET_GC_ENABLED(enabled)
  js_set_gc_enabled(OBJ, enabled)
END SUB

' It sets a flag that will cause the interpreter to throw an Interrupted Error
SUB INTERRUPT
  js_interrupt(OBJ)
END SUB

' Returns last parser error message
FUNCTION GET_ERROR
  GET_ERROR = js_get_parser_error(OBJ)
END FUNCTION

' Make numeric primitive value
FUNCTION MK_NUMBER(num)
  MK_NUMBER = js_mk_number(OBJ, num)
END FUNCTION

' Returns number value stored in `v7_val_t` as `double`
FUNCTION GET_DOUBLE(v)
  GET_DOUBLE = js_get_double(OBJ, v)
END FUNCTION

' Returns number value stored in `v7_val_t` as `int`. If the number
' value is not an integer, the fraction part will be discarded.
FUNCTION GET_INT(v)
  GET_INT = js_get_int(OBJ, v)
END FUNCTION

' Returns true if given value is a primitive number value
FUNCTION IS_NUMBER(v)
  IS_NUMBER = js_is_number(v)
END FUNCTION

' Make boolean primitive value (either `true` or `false`)
FUNCTION MK_BOOLEAN(is_true)
  MK_BOOLEAN = js_mk_boolean(OBJ, is_true)
END FUNCTION

' Returns boolean stored in `v7_val_t`: 0 for `false` or
' non-boolean, non-0 for `true`
FUNCTION GET_BOOL(v)
  GET_BOOL = js_get_bool(OBJ, v)
END FUNCTION

' Returns `true` if given value is a primitive boolean value
FUNCTION IS_BOOLEAN(v)
  IS_BOOLEAN = js_is_boolean(v)
END FUNCTION

' Make `null` primitive value
FUNCTION MK_NULL
  MK_NULL = js_mk_null()
END FUNCTION

' Returns true if given value is a primitive `null` value
FUNCTION IS_NULL(v)
  IS_NULL = js_is_null(v)
END FUNCTION

' Make `undefined` primitive value
FUNCTION MK_UNDEFINED
  MK_UNDEFINED = js_mk_undefined()
END FUNCTION

' Returns true if given value is a primitive `undefined` value
FUNCTION IS_UNDEFINED(v)
  IS_UNDEFINED = js_is_undefined(v)
END FUNCTION

' Make JavaScript value that holds C/C++ `void *` pointer
FUNCTION MK_FOREIGN
  MK_FOREIGN = js_mk_foreign(OBJ)
END FUNCTION

' Returns `void *` pointer stored in `v7_val_t`
' Returns NULL `undef` if the value is not a foreign pointer
FUNCTION GET_PTR(v)
  GET_PTR = js_get_ptr(OBJ, v)
END FUNCTION

' Returns true if given value holds `void *` pointer
FUNCTION IS_FOREIGN(v)
  IS_FOREIGN = js_is_foreign(v)
END FUNCTION

' Creates a string primitive value
FUNCTION MK_STRING(strval)
  MK_STRING = js_mk_string(OBJ, strval, LEN(strval), 1)
END FUNCTION

' Returns true if given value is a primitive string value
FUNCTION IS_STRING(v)
  IS_STRING = js_is_string(v)
END FUNCTION

' Returns a pointer to the string stored in `v7_val_t`
FUNCTION GET_STRING(v)
  GET_STRING = js_get_string(OBJ, v)
END FUNCTION

' Returns a pointer to the string stored in `v7_val_t`
' Returns NULL `undef` if the value is not a string or
' if the string is not compatible with a C string
FUNCTION GET_CSTRING(v)
  GET_CSTRING = js_get_cstring(OBJ, v)
END FUNCTION

' Make an empty object
FUNCTION MK_OBJECT
  MK_OBJECT = js_mk_object(OBJ)
END FUNCTION

' Returns true if the given value is an object or function
FUNCTION IS_OBJECT(v)
  IS_OBJECT = js_is_object(v)
END FUNCTION

' Get object's prototype.
FUNCTION GET_PROTO(object)
  GET_PROTO = js_get_proto(OBJ, object)
END FUNCTION

' Set object's prototype. Return old prototype or undefined on error
FUNCTION SET_PROTO(object, proto)
  SET_PROTO = js_set_proto(OBJ, object, proto)
END FUNCTION

' Lookup property `name` in object `obj`. If `obj` holds no such property,
' an `undefined` value is returned
FUNCTION GETS(object, objname)
  GETS = js_get(OBJ, object, objname, LEN(objname))
END FUNCTION

' Define object property, similar to JavaScript `Object.defineProperty()`
FUNCTION DEF(object, objname, attr, value)
  DEF = js_def(OBJ, object, objname, LEN(objname), attr, value)
END FUNCTION

' Set object property. Behaves just like JavaScript assignment
FUNCTION SETS(object, objname, value)
  SETS = js_set(OBJ, object, objname, LEN(objname), value)
END FUNCTION

' Delete own property `name` of the object `obj`
' Does not follow the prototype chain
FUNCTION DEL(object, objname)
  DEL = js_del(OBJ, object, objname, LEN(objname))
END FUNCTION

' Returns true if the object is an instance of a given constructor / class name
FUNCTION IS_INSTANCEOF(object, classname)
  IS_INSTANCEOF = js_is_instanceof(OBJ, object, classname)
END FUNCTION

' Returns true if the object is an instance of a given constructor object class
FUNCTION IS_INSTANCEOF_V(object, objclass)
  IS_INSTANCEOF_V = js_is_instanceof_v(OBJ, object, objclass)
END FUNCTION

' Custom multi-property `GET` function
FUNCTION GET_PROPERTIES(object, proparray)
  LOCAL objname, value, attr, propcnt
  objname = ""
  value = 0
  attr = 0
  propcnt = 1
 ' UNDEF proparray
 js_init_prop_iter_ctx(OBJ, object)
  WHILE js_next_prop(OBJ, objname, value, attr) <> undef
    proparray[propcnt, 0] = js_get_string(OBJ, objname)
    proparray[propcnt, 1] = js_get_int(OBJ, value)
    proparray[propcnt, 2] = attr
    propcnt += 1
  WEND
  js_destruct_prop_iter_ctx(OBJ)
  GET_PROPERTIES = propcnt - 1
END FUNCTION

' Make an empty array object
FUNCTION MK_ARRAY
  MK_ARRAY = js_mk_array(OBJ)
END FUNCTION

' Returns true if given value is an array object
FUNCTION IS_ARRAY(object)
  IS_ARRAY = js_is_array(OBJ, object)
END FUNCTION

' Returns length on an array. If `object` is not an array, 0 is returned
FUNCTION ARRAY_LENGTH(object)
  ARRAY_LENGTH = js_array_length(OBJ, object)
END FUNCTION

' Insert `value` in `object` at the end of the array
FUNCTION ARRAY_PUSH(object, value)
  ARRAY_PUSH = js_array_push(OBJ, object, value)
END FUNCTION

'  Return array member at index `index`. If `index` is out of bounds, undefined is returned
FUNCTION ARRAY_GET(object, index)
  ARRAY_GET = js_array_get(OBJ, object, index)
END FUNCTION

' Insert value `v` into `arr` at 'index`
FUNCTION ARRAY_SET(object, index, value)
  ARRAY_SET = js_array_set(OBJ, object, index, value)
END FUNCTION

' Delete value in array `arr` at index `index`, if it exists
SUB ARRAY_DEL(object, index)
   js_array_del(OBJ, object, index)
END SUB

' Execute JavaScript `js_code`
' The result of evaluation is stored in the `return` variable
' The 'ok' argument will contain the function's execution success status flag
FUNCTION EXEC(code, ok)
  EXEC = js_exec(OBJ, code, ok)
END FUNCTION

' Same as `v7_exec()`, but loads source code from `path` file
FUNCTION EXEC_FILE(codepath, ok)
  EXEC_FILE = js_exec_file(OBJ, codepath, ok)
END FUNCTION

' Parse `json_code`
' The result of evaluation is stored in the `return` variable
' The 'ok' argument will contain the function's parse success status flag
FUNCTION PARSE_JSON(json_code, ok)
  PARSE_JSON = js_parse_json(OBJ, json_code, ok)
END FUNCTION

' Same as `v7_parse_json()`, but loads `json_code` from `path` file
FUNCTION PARSE_JSON_FILE(json_code_file, ok)
  PARSE_JSON_FILE = js_parse_json_file(OBJ, json_code_file, ok)
END FUNCTION

' Call function `func` with arguments `args`, using `object` as `this`
' `args` should be an array containing arguments or `undefined`
FUNCTION APPLY(func, object, args)
  APPLY = js_apply(OBJ, func, object, args)
END FUNCTION

' Make RegExp object. For example, `regex` is `(.+)`, `flags` is `gi`.
FUNCTION MK_REGEXP(regex, flags, rcode)
  MK_REGEXP = js_mk_regexp(OBJ, regex, LEN(regex), flags, LEN(flags), rcode)
END FUNCTION

' Returns true if given value is a JavaScript RegExp object
FUNCTION IS_REGEXP(object)
  IS_REGEXP = js_is_regexp(OBJ, object)
END FUNCTION

' Generate string representation of the JavaScript value
FUNCTION STRINGIFY(object, convtype)
  STRINGIFY = js_stringify(OBJ, object, convtype)
END FUNCTION

' Output a string representation of the value to stdout followed by a newline
SUB PRINTIFY(object)
  js_println(OBJ, object)
END SUB


END MODULE
 

Hello JavaScript
IMPORT js.inc

JS::CREATE
PRINT JS::GET_INT(JS::EXEC("1 + 1")),"\n"
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ time scriba js_hello2.sb
2

real   0m0.026s
user   0m0.016s
sys   0m0.008s
jrs@jrs-laptop:~/sb/examples/js$


Fibonacci
IMPORT js.inc

jscode = """
function fibonacci(n) {
  if (n <= 2) {
    return 1;
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2);
  }
}

print(fibonacci(24));
"
""

JS::CREATE
JS::EXEC(jscode)
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_fibonacci.sb
46368
jrs@jrs-laptop:~/sb/examples/js$


Create object, property and attributes
IMPORT js.inc

JS::CREATE
myobj = JS::MK_OBJECT()
JS::DEF(myobj, "test", 0, JS::MK_NUMBER(64))
JS::SETS(myobj, "test", JS::MK_NUMBER(32))
JS::DEF(myobj, "test", JS::WRITABLE(FALSE) OR JS::PRESERVE_VALUE(),JS::MK_NULL())
JS::SETS(myobj, "test", JS::MK_NUMBER(16))
PRINT "test = ",JS::GET_INT(JS::GETS(myobj, "test")),"\n"
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_deftest.sb
test = 32
jrs@jrs-laptop:~/sb/examples/js$


Load .js file and get properties
IMPORT js.inc

JS::CREATE
JS::EXEC_FILE "properties.js"
propcnt = JS::GET_PROPERTIES(JS::GETS(JS::SYS,"test"), proparray)
PRINT "Property\tValue\tAttribute\n"
FOR i = 1 to propcnt
  PRINT proparray[i,0],"\t\t",proparray[i,1],"\t",proparray[i,2],"\n"
NEXT
JS::DESTROY
 
properties.js
var test = {};

Object.defineProperty(test, 'a', {
  value: 1,
  writable: true,
  enumerable: true,
  configurable: true
});

Object.defineProperty(test, 'b', {
  value: 2,
  writable: false,
  enumerable: false,
  configurable: false
});
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_propfile.sb
Property   Value   Attribute
b      2   7
a      1   0
jrs@jrs-laptop:~/sb/examples/js$


Call JavaScript function
IMPORT js.inc

jscode = """
var sum = function(a, b, c) {
  print (c);
  return a + b; };
"
""

JS::CREATE()
JS::EXEC(jscode)
func = JS::GETS(JS::SYS, "sum")
args = JS::MK_ARRAY()
JS::ARRAY_PUSH(args, JS::MK_NUMBER(123.0))
JS::ARRAY_PUSH(args, JS::MK_NUMBER(0.456))
JS::ARRAY_PUSH(args, JS::MK_STRING("Script BASIC"))
result = JS::APPLY(func, 0, args, rcode)
PRINT FORMAT("Result: %g\n", JS::GET_DOUBLE(result))
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_callfunc.sb
Script BASIC
Result: 123.456
jrs@jrs-laptop:~/sb/examples/js$


Describe Properties with JavaScript
IMPORT js.inc

' Create JavaScript instance
JS::CREATE

' Create JavaScript object
JS::EXEC("var myobj = {};")
myobj = JS::GETS(JS::SYS, "myobj")

' Create object property
JS::DEF(myobj, "test", JS::WRITABLE(TRUE), JS::MK_NUMBER(64))

' Describe object properties with JavaScript
jscode = """
var descriptors = {};

Object.keys(myobj).forEach(function(key) {
    descriptors[key] = Object.getOwnPropertyDescriptor(myobj, key);
});

var objdesc = JSON.stringify(descriptors);
"
""
JS::EXEC(jscode)

' Return JSON formatted result string
PRINT JS::GET_STRING(JS::GETS(JS::SYS, "objdesc")),"\n"

' Release JavaScript instance
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_defobj.sb
{"test":{"configurable":true,"enumerable":true,"writable":true,"value":64}}
jrs@jrs-laptop:~/sb/examples/js$


JSON / Stringify
IMPORT js.inc

JS::CREATE
myobj = JS::MK_OBJECT()
JS::DEF(myobj, "myprop_1", 0, JS::MK_NUMBER(64))
JS::DEF(myobj, "myprop_2", 0, JS::MK_NUMBER(1.23))
JS::DEF(myobj, "myprop_3", 0, JS::MK_STRING("JavaScript"))
PRINT JS::STRINGIFY(myobj, JS::JSON),"\n"
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ scriba js_stringify.sb
{"myprop_3":"JavaScript","myprop_2":1.23,"myprop_1":64}
jrs@jrs-laptop:~/sb/examples/js$


JavaScript Regular Expression
IMPORT js.inc

jscode = """
var output = ['---------- Original String\\n', names + '\\n'];

// Prepare two regular expression patterns and array storage.
// Split the string into array elements.

// pattern: possible white space then semicolon then possible white space
var pattern = /\\s*;\\s*/;

// Break the string into pieces separated by the pattern above and
// store the pieces in an array called nameList
var nameList = names.split(pattern);

// new pattern: one or more characters then spaces then characters.
// Use parentheses to "
memorize" portions of the pattern.
// The memorized portions are referred to later.
pattern = /(\\w+)\\s+(\\w+)/;

// New array for holding names being processed.
var bySurnameList = [];

// Display the name array and populate the new array
// with comma-separated names, last first.
//
// The replace method removes anything matching the pattern
// and replaces it with the memorized string—second memorized portion
// followed by comma space followed by first memorized portion.
//
// The variables $1 and $2 refer to the portions
// memorized while matching the pattern.

output.push('---------- After Split by Regular Expression');

var i, len;
for (i = 0, len = nameList.length; i < len; i++) {
  output.push(nameList[i]);
  bySurnameList[i] = nameList[i].replace(pattern, '$2, $1');
}

// Display the new array.
output.push('---------- Names Reversed');
for (i = 0, len = bySurnameList.length; i < len; i++) {
  output.push(bySurnameList[i]);
}

// Sort by last name, then display the sorted array.
bySurnameList.sort();
output.push('---------- Sorted');
for (i = 0, len = bySurnameList.length; i < len; i++) {
  output.push(bySurnameList[i]);
}

output.push('---------- End');

var retstr = output.join('\\n');
"
""

' The name string contains multiple spaces and tabs,
' and may have multiple spaces between first and last names.

JS::CREATE
JS::EXEC("var names = 'Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ';")
JS::EXEC(jscode)
PRINT JS::GET_STRING(JS::GETS(JS::SYS, "retstr"))
JS::DESTROY
 

jrs@jrs-laptop:~/sb/examples/js$ time scriba js_regexp.sb
---------- Original String

Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand

---------- After Split by Regular Expression
Harry Trump
Fred Barney
Helen Rigby
Bill Abel
Chris Hand
---------- Names Reversed
Trump, Harry
Barney, Fred
Rigby, Helen
Abel, Bill
Hand, Chris
---------- Sorted
Abel, Bill
Barney, Fred
Hand, Chris
Rigby, Helen
Trump, Harry
---------- End
real   0m0.030s
user   0m0.028s
sys   0m0.000s
jrs@jrs-laptop:~/sb/examples/js$

« Last Edit: October 24, 2017, 02:16:12 am by support »