cesanta / elk Goto Github PK
View Code? Open in Web Editor NEWA low footprint JavaScript engine for embedded systems
License: Other
A low footprint JavaScript engine for embedded systems
License: Other
Hello! First of all, the library is awesome! ๐
But I have question. Can we access updated values of variables? For example:
int main(void) {
char jmem[200];
struct js *js = js_create(jmem, sizeof(jmem));
jsval_t jCnt = js_mknum(js, 8);
js_set(js, js_glob(js), "cnt", jCnt);
js_eval(js, "cnt=3;", ~0);
printf("jCnt: %s\n", js_str(js, jCnt)); // output: "jCnt: 8"
return 0;
}
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
Elk Library: release 0.0.3 (Installed manually into Arduino IDE library folder)
ESP8266 BOARD: 2.5.2 (Installed with board manager from Arduino IDE)
TEST CODE: (ArduinoBlink.ino)
#include <elk.h> // Sketch -> Add File -> elk.h and elk.c
extern "C" void myDelay(int milli) {
delay(milli);
}
extern "C" void myWrite(int pin, int val) {
digitalWrite(pin, val);
}
void setup() {
void *mem = malloc(500);
struct js *js = js_create(mem, 500);
js_ffi(js, myDelay, "vi");
js_ffi(js, myWrite, "vii");
js_eval(js,
"while (1) { "
" myWrite(13, 0); "
" myDelay(100); "
" myWrite(13, 1); "
" myDelay(100); "
"}",
-1);
}
void loop() {
delay(1000);
}
ESP8266 OUTPUT:
/home/name/.arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: ArduinoBlink.ino.elf section `.text1' will not fit in region `iram1_0_seg'
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Generic ESP8266 Module.
NOTES:
Generic ESP8266 4MB (1MB spiffs)
AVR OUTPUT:
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a: In function `js_object_first_prop':
/Users/lsm/src/cpqelk/elk.c:517: undefined reference to `__mulhi3'
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a: In function `js_object_key':
/Users/lsm/src/cpqelk/elk.c:529: undefined reference to `__mulhi3'
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a: In function `js_ref':
/Users/lsm/src/cpqelk/elk.c:787: undefined reference to `__mulhi3'
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a: In function `js_get_prop':
/Users/lsm/src/cpqelk/elk.c:802: undefined reference to `__mulhi3'
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a: In function `js_object_first_prop':
/Users/lsm/src/cpqelk/elk.c:517: undefined reference to `__mulhi3'
/home/name/Arduino/libraries/elk/src/atmega328p/libelk.a:/Users/lsm/src/cpqelk/elk.c:657: more undefined references to `__mulhi3' follow
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino/Genuino Uno.
NOTES:
I had to rename avr to atmega328p in the src folder ...
I am not able to build on ubuntu linux with the following error;
/usr/bin/ld: /tmp/ccjf3pKm.o: undefined reference to symbol 'pow@@GLIBC_2.2.5'
//lib/x86_64-linux-gnu/libm.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Makefile:45: recipe for target 'cli' failed
make: *** [cli] Error 1
I added '-lm' to the CFLAGS in the Makefile to fix the problem ...
CFLAGS ?= -lm -W -Wall -Werror -Wno-deprecated -I.. -g -fsanitize=address,undefined -coverage $(EXTRA)
I am not sure how this will affect other platforms ...
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.19 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
From the elk github page ... it reads
All but !=, ==. Use !==, === instead
but the following code demonstrates that '===' isn't working (I also tested '==' ... as well as tested '!==' and '!=' with same result ... ERROR 1898)
code
v = js_eval(js, "if(1 === 1) { print('working ...'); return 1; } print('not working ...'); return 0;", 0);
Serial.print("test result: "); Serial.println(js_str(js, v));
js_gc(js, v);
result
test result: ERROR 1898
if I replace '===' with either the '>=' or '<=' then that works as expected ... but not what I need
result
"working ..."
test result: 1
Hi,
I'm trying to use this library on ESP8266 (Core 2.6.3,with Arduino IDE 1.8.12).
I added a C function "print" to JS,and found that: When calling this C function from JS with string as a parameter continuously,random characters appear at the end of the string.Even when calling not the same function continuously,random character will appear in the output from serial.But the first call outputed normal.That's was quiet strange.
My sketch files are here: BlinkyJS-lucy2003.zip
Note that I load scripts from SPIFFS,which means scripts will need to be uploaded by 'ESP8266 Sketch Data Upload' tool.Otherwise it will need to be wrote in the code.
Any solution?Thanks you.
Since that is a different issue, please open a new one - I'd appreciate a minimal example.
Originally posted by @cpq in #14 (comment)
When I use timer in JS code it makes esp32 crash. The code runs for some minutes, but then it crashes. Any idea of what should be?
`
7c8a3 2 JS.h:2071:js_timer_fn Calling JS: main();
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x40128533 PS : 0x00060a30 A0 : 0x8012c2ae A1 : 0x3ffb2540
A2 : 0xbff503a8 A3 : 0x3fff03a8 A4 : 0x7ff60000 A5 : 0x00000e2c
A6 : 0x3f401905 A7 : 0x00000004 A8 : 0xfffffffc A9 : 0x00000000
A10 : 0x00000000 A11 : 0x3ffceb14 A12 : 0x3ffc3ca8 A13 : 0x00000011
A14 : 0x3ffccfb8 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0xbff503a8 LBEG : 0x401284ac LEND : 0x40128500 LCOUNT : 0x00000002
Backtrace:0x40144900:0x3ffb25100x401487b1:0x3ffb2540 0x401489e9:0x3ffb2570 0x40148a71:0x3ffb2590 0x40148af9:0x3ffb25b0 0x40148bc5:0x3ffb25d0 0x40148cb5:0x3ffb25f0 0x40148d5d:0x3ffb2610 0x40148de1:0x3ffb2630 0x40147831:0x3ffb2650 0x40147a29:0x3ffb2690 0x40147bb1:0x3ffb26d0 0x40147d69:0x3ffb2700 0x40146067:0x3ffb2720 0x4014919d:0x3ffb2770 0x400ea921:0x3ffb27b0 0x4011fb4e:0x3ffb27d0 0x40150629:0x3ffb2820
#0 0x40144900:0x3ffb2510 in lkp at .pio/libdeps/latest_stable/elk/elk.c:589
#1 0x401487b1:0x3ffb2540 in lookup at .pio/libdeps/latest_stable/elk/elk.c:606
(inlined by) js_call_dot at .pio/libdeps/latest_stable/elk/elk.c:979
(inlined by) js_postfix at .pio/libdeps/latest_stable/elk/elk.c:995
(inlined by) js_unary at .pio/libdeps/latest_stable/elk/elk.c:1014
#2 0x401489e9:0x3ffb2570 in js_mul_div_rem at .pio/libdeps/latest_stable/elk/elk.c:1019
#3 0x40148a71:0x3ffb2590 in js_plus_minus at .pio/libdeps/latest_stable/elk/elk.c:1024
#4 0x40148af9:0x3ffb25b0 in js_shifts at .pio/libdeps/latest_stable/elk/elk.c:1028
#5 0x40148bc5:0x3ffb25d0 in js_comparison at .pio/libdeps/latest_stable/elk/elk.c:1033
#6 0x40148cb5:0x3ffb25f0 in js_equality at .pio/libdeps/latest_stable/elk/elk.c:1038
#7 0x40148d5d:0x3ffb2610 in js_bitwise_and at .pio/libdeps/latest_stable/elk/elk.c:1042
#8 0x40148de1:0x3ffb2630 in js_bitwise_xor at .pio/libdeps/latest_stable/elk/elk.c:1046
#9 0x40147831:0x3ffb2650 in js_bitwise_or at .pio/libdeps/latest_stable/elk/elk.c:1050
(inlined by) js_logical_and at .pio/libdeps/latest_stable/elk/elk.c:1054
#10 0x40147a29:0x3ffb2690 in js_logical_or at .pio/libdeps/latest_stable/elk/elk.c:1072
#11 0x40147bb1:0x3ffb26d0 in js_ternary at .pio/libdeps/latest_stable/elk/elk.c:1090
#12 0x40147d69:0x3ffb2700 in js_assignment at .pio/libdeps/latest_stable/elk/elk.c:1112
#13 0x40146067:0x3ffb2720 in js_expr at .pio/libdeps/latest_stable/elk/elk.c:1122
(inlined by) js_stmt at .pio/libdeps/latest_stable/elk/elk.c:1309
#14 0x4014919d:0x3ffb2770 in js_eval at .pio/libdeps/latest_stable/elk/elk.c:1398
`
Build started: Project: ble_freertos_watch
*** Using Compiler 'V5.06 update 7 (build 960)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'ble_freertos_watch'
compiling elk.c...
Internal fault: [0xd365b7:5060960] in js_call_params
Please contact your supplier.
compiling startup_keil.s...
linking...
.\bin\ble_freertos_watch.axf: error: L6002U: Could not open file .\bin\elk.o: No such file or directory
Finished: 0 information, 0 warning, 0 error and 1 fatal error messages.
".\bin\ble_freertos_watch.axf" - 1 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed: 00:00:04
Hello and thank you for sharing your code. It's a wonderful lightweight scripting engine that's easy to use while providing powerful possibilities.
While trying to use it for my ESP8266 device, I unfortunately ran into some memory issues.
This was the simple script I tried to run:
let n=10; while(n-->0) { console.log("u"+str(n)+":"+str(usage())+"\n"); }
The console.log function is a simple FFI printf addition I used to get debug output and usage calls your js_usage to report the percentage of memory used.
When running this script I quickly ran into an OOM error. So first I increased my js-buffer, but that wasn't enough to allow a much greater amount of iterations (say n=100). I noticed that each iteration would substantially increase the amount of memory used. At the global scope the memory would be released by the garbage collection, but not within a block.
After three days of debugging, I learned more of your code and I found a solution that worked for me.
After adding some debug statements it appeared that the Fast scope GC line within js_block()
never really released any memory:
printf("js_block[s%u] pre GC %u (1:%u, 2:%u) \n", (jsoff_t) vdata(js->scope), js->brk, brk1, brk2);
if (js->brk == brk2) js->brk = brk1; // Fast scope GC (ORIGINAL CODE)
printf("js_block[s%u] post GC %u-%u=%u\n", (jsoff_t) vdata(js->scope), js->brk, brk1, js->brk-brk1);
I saw that js->brk
would always be different from brk2
. Skipping that check to always call js->brk = brk1
did set the memory-scope back, but resulted in corruption for instance with string variables that had text added within the loop.
What finally worked for me was to call the slower js_gc()
function instead:
printf("js_block[s%u] pre GC %u (1:%u, 2:%u) \n", (jsoff_t) vdata(js->scope), js->brk, brk1, brk2);
if((js->flags & F_NOEXEC) != F_NOEXEC) // only do gc() when executing (i.e not when defining function in object)
js_gc(js); // Slower scope GC (NEW CODE)
printf("js_block[s%u] post GC %u-%u=%u\n", (jsoff_t) vdata(js->scope), js->brk, brk1, js->brk-brk1);
This modification allowed me to run much larger iterations without loosing any memory.
From the looks of it, this issue was introduced in one of the may-2021 releases where a call to js_gc()
within js_block()
was removed, but I guess you have a better environment to debug and improve your code. I just wanted to share my experience and give people running into the same issue a possible solution (providing no guarantee that what worked for me will also work for you).
Edit: had some issues with objects containing functions. Fixed by checking for F_NOEXEC
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.16 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
I'm having difficulty with some code I'm trying to get working on the esp32 ... I believe my problem stems from my use of the Bitwise AND operator ... here is a snippet
code snippet
js_eval(js, "let rainbow =
function(wait) {
b = 0;
while(b < 1280) {
c = 0;
while(c < numPixels()) {
setPixelColor32(c, Wheel(((c * 256 / numPixels()) + b) & 255));
c++;
}
show();
delay(wait);
b++;
}
};
", 0);
I am unable to build the unit_test.c file ... it seems to be out of step with the rest of development.
also ... there are no test for the compound bitwise &= (and) and |= (or) operators ... here are the examples I added to the test_basic() function ...
assert(ev(js, "a=5;1;", "1"));
assert(ev(js, "a&=3;a;", "1"));
assert(ev(js, "a|=3;a;", "3"));
unlike with the predecessor (mjs) there is no destroy function ... is there another way to free and restart the vm without rebooting? can I simply use free() ??
create
struct js *js = js_create(malloc(ALLOC), ALLOC);
destroy
free(js);
I know that redefining variables and functions has been done in other JS environments ... but I'm not sure if it's actually proper javascript ... in testing it out with Elk ... I have experienced success and failure and i'd like to ask if first it's proper javascript ... and second if so ... will elk also support it? from my testing it seams to work as long as the string is shorter (number of characters) than the previous length defined (for variables, function, objects) and it seams to work fine with numbers ... also this too seams to work ... but not sure if it's good practice :)
let bee = function(x,s) {x*s};
function(x,s) {x*s}
bee
function(x,s) {x*s}
bee(1,2);
2
let tree = function() {};
function() {}
bee(1,2);
2
tree = bee;
function(x,s) {x*s}
tree
function(x,s) {x*s}
tree(1,2);
2
for (int i = 0; i < nops; i++) {
uint8_t idx = ops[i], op = vdata(stk[idx]) & 255, ri = idx;
bool unary = is_unary(op), rassoc = is_right_assoc(op);
bool needleft = unary && rassoc ? false : true;
bool needright = unary && !rassoc ? false : true;
jsval_t left = mkval(T_UNDEF, 0), right = mkval(T_UNDEF, 0);
mask |= 1 << idx;
// printf(" OP: %d idx %d %d%d\n", op, idx, needleft, needright);
if (needleft) {
if (idx < 1) return js_err(js, "bad expr");
mask |= 1 << (idx - 1);
ri = getri(mask, idx);
left = stk[ri];
if (is_err(left)) return js_err(js, "bad expr");
}
if (needright) {
mask |= 1 << (idx + 1);
if (idx + 1 >= n) return js_err(js, "bad expr");
right = stk[idx + 1];
if (is_err(right)) return js_err(js, "bad expr");
}
stk[ri] = do_op(js, op, left, right); // Perform operation
if (is_err(stk[ri])) return stk[ri]; // Propagate error
}
In the above code, I know that it is the traversal operator, and then get the lvalue and rvalue.
But why use mask to perform some magical displacement operations (for example, 1<< idx, 1<< (idx-1)), and what does getri
do? I am very confused about this. I hope you can explain how you are The design idea of this piece.
thank you very much!!!
Hi ๐,
First thanks for this awesome lib :)
Unfortunately, it no longer seems functional on esp32. Impossible to compile, even the example provided
I tried to go back to old versions of arduino and the software of the esp32 board because it worked well before, but without success. I can't figure out what has changed since my last use of elk.
Here is the error output :
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_gc':
elk.c:(.text+0x7d0): multiple definition of `js_gc'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x7d0): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_fmt':
elk.c:(.text+0x139c): multiple definition of `js_fmt'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x139c): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_str':
elk.c:(.text+0x15d8): multiple definition of `js_str'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x15d8): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_eval':
elk.c:(.text+0x1604): multiple definition of `js_eval'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x1604): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_parse':
elk.c:(.text+0x2300): multiple definition of `js_parse'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x2300): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_ffi':
elk.c:(.text+0x2a1c): multiple definition of `js_ffi'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x2a1c): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_import':
elk.c:(.text+0x2a70): multiple definition of `js_import'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x2a70): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_info':
elk.c:(.text+0x2ac0): multiple definition of `js_info'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x2ac0): first defined here
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a: In function `js_create':
elk.c:(.text+0x2af8): multiple definition of `js_create'
/Users/esellan/Documents/Arduino/libraries/elk/src/esp32/libelk.a:elk.c:(.text+0x2af8): first defined here
collect2: error: ld returned 1 exit status
exit status 1
Erreur de compilation pour la carte ESP32 Dev Module
Let me know if you need any information about this issue
Thanks by advance
best regards
I think this library is great!
And I would like to point out that a common tool is using the same name
https://www.elastic.co/what-is/elk-stack
This is an acronym for Elastic Logstash && Kibana
It would be great if you did a bit of research any checked if there are other colliding names ( as I would this tool be unique and stand on it's own)
Best of luck!
Hi there! I have been facing an issue with my code that I am unable to find out a solution (I don't think it is a issue with the library). I am using MCP23017 over I2C with my esp32 and I am unable to create a function that works to digitalWrite on MCP23017. Could someone help me? My code is the Esp32JS example with these add.
This one is inside extern "C"
void mcp_write(int pin, bool val) { mcp1.digitalWrite(pin, val); }
This new line below
`js_set(js, js_glob(js), "gpio", gpio);
js_set(js, gpio, "mode", js_import(js, (uintptr_t) gpio_mode, "vii"));
js_set(js, gpio, "write", js_import(js, (uintptr_t) gpio_write, "vii"));
js_set(js, gpio, "read", js_import(js, (uintptr_t) gpio_read, "ii"));
js_set(js, gpio, "mcpwrite", js_import(js, (uintptr_t) mcp_write, "vib")); //my new mcp write`
When I do this I get this error:
Guru Meditation Error: Core 1 panic'ed (IntegerDivideByZero). Exception was unhandled.
Core 1 register dump:
PC : 0x4011b26b PS : 0x00060830 A0 : 0x8011b6e8 A1 : 0x3ffb1e10
A2 : 0x00000133 A3 : 0x3ffb1e9c A4 : 0x00000032 A5 : 0x3ffbef4c
A6 : 0x00004e20 A7 : 0x60013000 A8 : 0x00000113 A9 : 0x3ffb1df0
A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3ffb8548 A13 : 0x3ffcd8e4
A14 : 0x00002710 A15 : 0x3ffbef4c SAR : 0x0000001c EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
Backtrace: 0x4011b26b:0x3ffb1e10 0x4011b6e5:0x3ffb1e40 0x4010f97d:0x3ffb1e60 0x4010fa31:0x3ffb1e90 0x4010fab1:0x3ffb1ec0 0x4010fb3d:0x3ffb1ee0 0x4010fc87:0x3ffb1f00 0x400d7c39:0x3ffb1f20 0x400ec36d:0x3ffb1f40 0x400f8d34:0x3ffb1f80 0x4011c38d:0x3ffb1fb0 0x40089911:0x3ffb1fd0
Rebooting...
Defining this function gives no error (note the space in "function (x)"):
let fnBadSpace=function (x) { return(x+3); }
When calling this function ERROR: bad sig is reported:
fnBadSpace(10);
ERROR: bad sig
Note that when listing the function definition there is a space in the definition:
fnBadSpace(10);
" (x) { return(x+3); }"
Perhaps the parser should skip this space when defining the function?
(When testing the library it took me a while to discover that this space was the culprit)
I am unable to use the logical NOT (!) operator ... looking at your source code from the unit_test.c the following test fail ...
assert(ev(js, "a=true;a", "true"));
assert(ev(js, "a=!a;a", "false"));
assert(ev(js, "!123", "false"));
assert(ev(js, "!0", "true"));
here's what I get when using the repl ...
js > let a=true;a
true
js > a=!a;a
ERROR: type mismatch
js > a=!a;a
ERROR: type mismatch
js > !123
ERROR: unknown op 104
js > !0
ERROR: unknown op 104
js > a=!(a);a
ERROR: type mismatch
js > !(a);
ERROR: type mismatch
js > a;
true
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
Elk Library: release 0.0.7 (Installed manually into Arduino IDE library folder)
(the same as 0.0.6 since nothing changed for the esp8266 ...)
ESP8266 BOARD: 2.5.2 (Installed with board manager from Arduino IDE)
ArduinoBlink.ino.elf section
.text1' will not fit in region iram1_0_seg'
it seams that the esp8266 platform is not a priority ...
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.7 (Installed using Arduino IDE library manager)
Arduino AVR boards (Nano): 1.8.1 (Installed with board manager from Arduino IDE)
Directory for the Library
In order to test ... I had to rename the avr/ folder under the library src folder to atmega328p/
I am assuming the libelk.a file was indeed built targeting the atmega328p processor ... or I would expected it not to link ... or run otherwise.
Test Code:
Serial.println(js_eval(js,
"while (1) { "
" myWrite(13, 0); "
" myDelay(100); "
" myWrite(13, 1); "
" myDelay(100); "
"}",
-1));
Responce: This code should block and loop ... it doesn't it returns this right away ...
4286578688
Are there any plans to release the binary blob for the ESP8266 platform?
Hello again.
While further testing Elk on my ESP project and after incorporation of my previous fix, I encountered another issue with the garbage collection. It only occurs in certain circumstances and produces unpredictable behavior.
In my project it was very reproducible and failed every time I ran this minimized test script:
let fn=function(x) { let i=0; while(i<x) {res=res+"!"; i++; }; }; let res="123"; fn(3);
In my ESP-sketch this script results in a WDT-reset. Different variants of this script often wouldn't show the issue the same way.
The proper functioning should be that global variable res is set to the value of "123!!!".
After lengthy debugging by inserting debug dumps and debug printfs in js_stmt() and in js_delete_marked_entities() I think I found the issue. Long story short it appears that js_fixup_offsets() doesn't fixup the offset to upper for objects. Having an incorrect reference in upper can result in incorrect deletions in subsequent garbage collections, giving further issues, During my debug sessions I saw the upper reference remained the same after in-between T_STR values for res were deleted by CG. It think this issue floated to the surface now because of the more frequent garbage collection.
After first trying to understand your code, by analyzing debug output and based on that adding comments, I managed to make the above script function work without generating a WDT reset. This is the modified version of js_fixup_offsets():
static void js_fixup_offsets(struct js *js, jsoff_t start, jsoff_t size) {
// fixup all entities prior to moving data at start for deleting the start entity (which is marked for deletion)
for (jsoff_t n, v, off = 0; off < js->brk; off += n) { // start from 0!
v = loadoff(js, off); // load 4-byte offset value of item at off.
// For objects v is only the offset of its first property. For properties it is the offset of the next item (0 if first)
n = esize(v & ~GCMASK);
if (v & GCMASK) continue; // To be deleted, don't bother
if ((v & 3) != T_OBJ && (v & 3) != T_PROP) continue; // T_STR doesn't need further fixup
// Fixup first/next offset for values beyond starting point
if (v > start) saveoff(js, off, v - size); // save new offset (v-size) for first/next at off
// MMOLE 220216: proper fixup of upper offset for objects that don't fall under global scope (upper@0)
if ((v & 3) == T_OBJ) {
jsoff_t u = loadoff(js, off+sizeof(jsoff_t)); // load 4-byte offset value of upper
if(u > start)
saveoff(js, off+sizeof(jsoff_t), u - size); // fixup upper, checked for negatives
}
// fixup property, key and value
if ((v & 3) == T_PROP) {
// fixup key offset
jsoff_t koff = loadoff(js, off + sizeof(off));
if (koff > start) saveoff(js, off + sizeof(off), koff - size);
// fixup value data offset
jsval_t val = loadval(js, off + sizeof(off) + sizeof(off));
if (is_mem_entity(vtype(val)) && vdata(val) > start) {
// printf("MV %u %lu -> %lu\n", off, vdata(val), vdata(val) - size);
saveval(js, off + sizeof(off) + sizeof(off), mkval(vtype(val), vdata(val) - size));
}
}
}
// fixup callbacks
for (jsoff_t i = 0; i < js->ncbs; i++) {
jsoff_t base = js->size + i * 3 * sizeof(jsoff_t) + sizeof(jsoff_t);
jsoff_t o1 = loadoff(js, base), o2 = loadoff(js, base + sizeof(o1));
if (o1 > start) saveoff(js, base, o1 - size);
if (o2 > start) saveoff(js, base + sizeof(jsoff_t), o2 - size);
}
// Fixup js->scope
jsoff_t off = vdata(js->scope);
if (off > start) js->scope = mkval(T_OBJ, off - size);
}
Disclaimer: Please note that I only tried to fix this issue as I encountered it. Using my code is at your own risk. No guaranties given and no liability accepted. Unfortunately I am not able to provide support....
Would you consider releasing a WebAssembly version of elk? For the purpose of testing Elk code from within a web browser based editor.
Closuers are very useful for customers as an application programming scheme.
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.18 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
This is a continuation of issue #14 ...
below are snippets of the code to demonstrate what happens ... In the first example setPixelColor() gets called after WheelR() BUT before WheelG() or WheelB() are called ... so the g & b variables are always set to zero (0) ... setting it to a variable first solved the problem ... but it may still be a problem in some cases ...
NOT WORKING
v = js_eval(js, "let rainbow =
function(d) {
let j = 0, i;
while(j < 256) {
i = 0;
while(i < numPixels()) {
setPixelColor(i, WheelR((i + j) & 255), WheelG((i + j) & 255), WheelB((i + j) & 255));
i++;
}
show();
delay(d);
j++;
}
return j;
};
", 0);
WORKING
v = js_eval(js, "let rainbow =
function(d) {
let j = 0, i, p;
while(j < 256) {
i = 0;
while(i < numPixels()) {
p = (i + j) & 255;
setPixelColor(i, WheelR(p), WheelG(p), WheelB(p));
i++;
}
show();
delay(d);
j++;
}
return j;
};
", 0);
Here the problem is also with the function parameters and how they are being processed (order) ... again in the first example the setPixelColor() function gets called before the any of the WheelX() functions get called ... again leaving rgb variables all set to zero ... this is not the desired outcome ... however when I pass the first parameter to setPixelColor() as a pre-calculated variable ... it functions as expected ...
NOT WORKING
v = js_eval(js, "let theaterChaseRainbow =
function(wait) {
let j = 0, q, i, p;
while(j < 256) {
q = 0;
while(q < 3) {
i = 0;
while(i < 8) {
p = (i + j) % 255;
setPixelColor(i + q, WheelR(p), WheelG(p), WheelB(p));
i = i + 3;
}
show();
delay(wait);
i = 0;
while(i < 8) {
setPixelColor(i + q, 0, 0, 0);
i = i + 3;
}
q++;
}
j++;
}
return j;
};
", 0);
WORKING
v = js_eval(js, "let theaterChaseRainbow =
function(wait) {
let j = 0, q, i, p, r;
while(j < 256) {
q = 0;
while(q < 3) {
i = 0;
while(i < 8) {
p = (i + j) % 255;
r = i + q;
setPixelColor(r, WheelR(p), WheelG(p), WheelB(p));
i = i + 3;
}
show();
delay(wait);
i = 0;
while(i < 8) {
r = i + q;
setPixelColor(r, 0, 0, 0);
i = i + 3;
}
q++;
}
j++;
}
return j;
};
", 0);
are there any future plans to release the binary blob for the AVR platform?
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.19 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
While trying to work around the non-functioning 'equal' operator I encountered strange unexpected result from calling subsequent function calls (not executing) after using 'return' ... here again are comparisons of 'working' and 'not working' code snippets ...
Not Working
let loop = function() {
let curMi = millis();
if(curMi - patPr >= patIn) {
patPr = curMi;
patCu++;
if(patCu >= 9) patCu = 0;
}
if(curMi - pixPr >= pixIn) {
pixPr = curMi;
if(patCu >=8) {tCR(); return;}
if(patCu >=7) {rbC(); return;}
if(patCu >=6) {rb(); return;}
if(patCu >=5) {tC(0, 0, 127); return;}
if(patCu >=4) {tC(127, 0, 0); return;}
if(patCu >=3) {tC(127, 127, 127); return;}
if(patCu >=2) {cW(0, 0, 255); return;}
if(patCu >=1) {cW(0, 255, 0); return;}
if(patCu >=0) {cW(255, 0, 0); return;}
}
};
Working
let loop = function() {
let curMi = millis();
if(curMi - patPr >= patIn) {
patPr = curMi;
patCu++;
if(patCu >= 9) patCu = 0;
}
if(curMi - pixPr >= pixIn) {
pixPr = curMi;
if(patCu >=8) {if(patCu <=8) tCR();}
if(patCu >=7) {if(patCu <=7) rbC();}
if(patCu >=6) {if(patCu <=6) rb();}
if(patCu >=5) {if(patCu <=5) tC(0, 0, 127);}
if(patCu >=4) {if(patCu <=4) tC(127, 0, 0);}
if(patCu >=3) {if(patCu <=3) tC(127, 127, 127);}
if(patCu >=2) {if(patCu <=2) cW(0, 0, 255);}
if(patCu >=1) {if(patCu <=1) cW(0, 255, 0);}
if(patCu >=0) {if(patCu <=0) cW(255, 0, 0);}
}
};
I am planning on releasing a project that depends on the Elk Library and would like to have a (precompiled) binary firmware version available ... are there any restrictions under Elk's GPLv2 license to prevent distributing a project in a binary form? There would be acknowledgement for the origin of the code used, and the project source code would also be open sourced.
it would be nice to know which version of the elk library is being loaded. perhaps a define added to elk.h or even worst ... a function to return the library version ... ๐
#define ELK_VER "0.0.22"
Hi,
I found the length of result is fixed, for instance,
js_eval(js, "100.1234", ~0) has result 100.123
js_eval(js, "1000.1234", ~0) has result 1000.12
How to fix it?
Thank you!
Yang
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.17 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
I have code that was working correctly with 0.0.16 on the esp32 platform that stopped working with version 0.0.17 ... the problem seams to be with nested while loops ... this code was working on the esp32 ... untested on other platforms
Code snippet
js_eval(js, "let theaterChase =
function(color, wait) {
a = 0;
while(a < 10) {
b = 0;
while(b < 3) {
clear();
c = b;
while(c < numPixels()) {
setPixelColor32(c, color);
c = c + 3;
}
show();
delay(wait);
b++;
}
a++;
}
};
", 0);
Hi,
Thanks for the nice lib. I found a small bug. The mistakes within while loop cannot be reported correctly.
Case1:
let a = 0;
a = a + 1 + unknown_var;
a;
Here are the correct report:
Error reported: 'unknown_var' not found
let a = 0;
let i = 0;
while (i<4)
{
a = a + 1 + unknown_var;
i++;
}
a;
The result is:
Returned value is string: undefined
Hello,
I've stumbled upon a bug in do_op
when handling TOK_POSTINC
(and TOK_POSTDEC
) assignment.
There's a missing type check for lhs, which causes it to be used directly instead of as an offset into variables (if lhs was an object).
static jsval_t do_assign_op(struct js *js, uint8_t op, jsval_t l, jsval_t r) {
...
jsval_t res = do_op(js, m[op - TOK_PLUS_ASSIGN], resolveprop(js, l), r);
assign(js, l, res);
in which resolveprop(js, l)
will return l
(T_NUM
)
calling do_op
with TOK_POSTINC or TOK_POSTDEC, is turned into do_assign_op(..., TOK_PLUS_ASSIGN|TOK_MINUS_ASSIGN, lhs, ...)
with lhs being a number (so resolveprop(..., lhs) = lhs
).
This causes OOB in struct js { uint8_t *mem; }
.
#include <stdio.h>
#include "elk.h"
int main(void) {
char mem[200];
struct js *js = js_create(mem, sizeof(mem)); // Create JS instance
jsval_t result = js_eval(js, "1.1--;", ~0); // Call sum
printf("result: %s\n", js_str(js, result)); // result: 7
return 0;
}
This causes a contrived memory corruption, bug somewhat controllable:
0x403d80 <saveval+32> mov qword ptr [rax + rdx], rdi
With rax pointing to js.mem
, rdx set to 0x999999a0
and rdi to the full float 0x3fb99999999999a0
The corruption is given as:
*(js.mem+offset) = (val << 32) | offset;
Adding a type check to lhs before do_assign_op
might be enough:
if (vtype(lhs) != T_OBJ && vtype(lhs) != T_CODEREF) return js_err(js, "bad lhs");
As such:
--- a/elk.c
+++ b/elk.c
@@ -154,6 +154,7 @@ static void saveoff(struct js *js, jsoff_t off, jsoff_t val) { memcpy(&js->mem[o
static void saveval(struct js *js, jsoff_t off, jsval_t val) { memcpy(&js->mem[off], &val, sizeof(val)); }
static jsoff_t loadoff(struct js *js, jsoff_t off) { jsoff_t v = 0; assert(js->brk <= js->size); memcpy(&v, &js->mem[off], sizeof(v)); return v; }
static jsoff_t offtolen(jsoff_t off) { return (off >> 2) - 1; }
static jsoff_t vstrlen(struct js *js, jsval_t v) { return offtolen(loadoff(js, vdata(v))); }
static jsval_t loadval(struct js *js, jsoff_t off) { jsval_t v = 0; memcpy(&v, &js->mem[off], sizeof(v)); return v; }
static jsval_t upper(struct js *js, jsval_t scope) { return mkval(T_OBJ, loadoff(js, vdata(scope) + sizeof(jsoff_t))); }
@@ -910,11 +911,23 @@ static jsval_t do_op(struct js *js, uint8_t op, jsval_t lhs, jsval_t rhs) {
case TOK_TYPEOF: return js_mkstr(js, typestr(vtype(r)), strlen(typestr(vtype(r))));
case TOK_CALL: return do_call_op(js, l, r);
case TOK_ASSIGN: return assign(js, lhs, r);
- case TOK_POSTINC: { do_assign_op(js, TOK_PLUS_ASSIGN, lhs, tov(1)); return l; }
- case TOK_POSTDEC: { do_assign_op(js, TOK_MINUS_ASSIGN, lhs, tov(1)); return l; }
+ case TOK_POSTINC: {
+
+ if (vtype(lhs) != T_OBJ && vtype(lhs) != T_CODEREF) return js_err(js, "bad lhs");
+ do_assign_op(js, TOK_PLUS_ASSIGN, lhs, tov(1));
+ return l;
+ }
+ case TOK_POSTDEC: {
+ if (vtype(lhs) != T_OBJ && vtype(lhs) != T_CODEREF) return js_err(js, "bad lhs");
+ do_assign_op(js, TOK_MINUS_ASSIGN, lhs, tov(1));
+ return l;
+ }
case TOK_NOT: if (vtype(r) == T_BOOL) return mkval(T_BOOL, !vdata(r)); break;
}
- if (is_assign(op)) return do_assign_op(js, op, lhs, r);
+ if (is_assign(op)) {
+ if (vtype(lhs) == T_OBJ || vtype(lhs) == T_CODEREF) return do_assign_op(js, op, lhs, r);
+ else return js_err(js, "bad lhs");
+ }
if (vtype(l) == T_STR && vtype(r) == T_STR) return do_string_op(js, op, l, r);
if (is_unary(op) && vtype(r) != T_NUM) return js_err(js, "type mismatch");
if (!is_unary(op) && op != TOK_DOT && (vtype(l) != T_NUM || vtype(r) != T_NUM)) return js_err(js, "type mismatch");
Hi,
I'd like to use elk and to allow JS code to access a global object representing the state of the system, but right now it seems the API does not allow to do that easily.
Basically I'd like to be able to define a global object with the state of my sensors, so that the JS code can observe it.
A possible way would be to do like in the README and define methods for all the properties, but this means they have to be re-evaluated each time, eg:
jsval_t state = js_mkobj(js);
jsval_t a_jsval_imported_method_to_getSensor1 = js_import(...);
js_set(js, state, "getSensor1", a_jsval_imported_method_to_getSensor1);
jsval_t a_jsval_imported_method_to_getSensor2 = js_import(...);
js_set(js, state, "getSensor2", a_jsval_imported_method_to_getSensor2);
another option would be to use js_eval
to create on-the-fly the value, but this means we have to serialize the value to a string, and then have elk parse it again
jsval_t state = js_mkobj(js);
js_set(js, state, "getSensor1", js_eval(..., "0.5"));
js_set(js, state, "getSensor2", js_eval(..., "61"));
what I'd like is a simple way to build jsval_t from standard values exposed in the API to allow doing something like:
jsval_t state = js_mkobj(js);
js_set(js, state, "getSensor1", js_float(0.5));
js_set(js, state, "getSensor2", js_int(61));
I'm trying this code
print("what is the value?");
let obj = {sensor: 10.0}
if (obj.sensor >= 1) {
print("greater");
} else {
print("smaller");
};
which correctly shows the first "what is the value?" line, but then exits without showing either of the other print line, and I'm not sure why?
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
elk Library: version 0.0.11 (Installed using Arduino IDE library manager)
ESP32 boards (DEVKIT): 1.0.4 (Installed with board manager from Arduino IDE)
Test Code
#include "elk.h" // Add Elk library
extern "C" void myDelay(int milli) { delay(milli); }
extern "C" void myWrite(int pin, int val) { digitalWrite(pin, val); }
extern "C" void myMode(int pin, int mode) { pinMode(pin, mode); }
struct js *js;
void setup() {
Serial.begin(115200);
Serial.println();
js = js_create(malloc(700), 700);
Serial.println("malloc done");
js_import(js, "f1", (uintptr_t) myDelay, "vi");
js_import(js, "f2", (uintptr_t) myWrite, "vii");
js_import(js, "f3", (uintptr_t) myMode, "vii");
Serial.println("imports done");
Serial.println(js_eval(js, "f3(2, 1);", 0)); // Set LED pin to OUTPUT mode
}
void loop() {
Serial.println(js_eval(js, "f1(200); f2(2, 1); f1(200); f2(2, 0);", 0));
}
Response
ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
malloc done
Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400d18e7 PS : 0x00060130 A0 : 0x800d3461 A1 : 0x3ffb1f00
A2 : 0x00000000 A3 : 0x3f401333 A4 : 0x00000002 A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x69760031 A9 : 0x3ffb1f20
A10 : 0x00000002 A11 : 0x3f4014eb A12 : 0x0000000b A13 : 0x0000ff00
A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x0000001f EXCCAUSE: 0x0000001c
EXCVADDR: 0x0000002c LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace: 0x400d18e7:0x3ffb1f00 0x400d345e:0x3ffb1f20 0x400d0f09:0x3ffb1f80 0x400d3d4f:0x3ffb1fb0 0x40088215:0x3ffb1fd0
GC right now seems to compact heap but it does compact it in a really slow way and as far as I understood it walks the entire heap when it changes a single reference. Maybe it is worth having mark&sweep with a linked list allocator instead of such a slow GC algorithm?
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
Elk Library: release 0.0.15 (Installed manually into Arduino IDE library folder)
ESP8266 BOARD: 2.5.2 (Installed with board manager from Arduino IDE)
Test Code
#include "elk.h" // Add Elk library
extern "C" void myDelay(int milli) { delay(milli); }
extern "C" void myWrite(int pin, int val) { digitalWrite(pin, val); }
extern "C" void myMode(int pin, int mode) { pinMode(pin, mode); }
struct js *js;
void setup() {
js = js_create(malloc(700), 700);
js_import(js, "f1", (uintptr_t) myDelay, "vi");
js_import(js, "f2", (uintptr_t) myWrite, "vii");
js_import(js, "f3", (uintptr_t) myMode, "vii");
js_eval(js, "f3(2, 1);", 0); // Set LED pin to OUTPUT mode ... tried f3(2, 2) also ...
}
void loop() {
js_eval(js, "f1(200); f2(2, 1); f1(200); f2(2, 0);", 0);
}
build
Sketch uses 272896 bytes (26%) of program storage space. Maximum is 1044464 bytes.
Global variables use 28420 bytes (34%) of dynamic memory, leaving 53500 bytes for local variables. Maximum is 81920 bytes.
just reboots ...
results
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v8b899c12
~ld
over and over ...
cc -o elk examples/posix/main.c -I src -L src/linux-x64 -ldl -lelk
/usr/bin/ld: skipping incompatible src/linux-x64/libelk.a when searching for -lelk
/usr/bin/ld: cannot find -lelk
collect2: error: ld returned 1 exit status
code:
#include "elk.h"
struct js *js;
char buff[100];
void setup() {
Serial.begin(115200);
void* m=malloc(10000);
js = js_create(m, 10000);
js_eval(js, "let num1=0;", 0);
char buff2[10];
for(int i=0;i<200;i++) Serial.printf("%d = %s\n",i,js_fmt(js,js_eval(js,itoa(i,buff2,10),0),buff,100));
Serial.printf("num89: %s\n",js_fmt(js,js_eval(js,"89",0),buff,100));
Serial.printf("num90: %s\n",js_fmt(js,js_eval(js,"90",0),buff,100));
Serial.printf("num99: %s\n",js_fmt(js,js_eval(js,"99",0),buff,100));
Serial.printf("num100: %s\n",js_fmt(js,js_eval(js,"100",0),buff,100));
}
void loop() {}
output:
01:58:15.506 -> 0 = 0
01:58:15.506 -> 1 = 1
01:58:15.506 -> 2 = 2
01:58:15.506 -> 3 = 3
01:58:15.506 -> 4 = 4
01:58:15.506 -> 5 = 5
01:58:15.506 -> 6 = 6
01:58:15.506 -> 7 = 7
01:58:15.506 -> 8 = 8
01:58:15.506 -> 9 = undefined
01:58:15.506 -> 10 = 10
01:58:15.506 -> 11 = 11
01:58:15.506 -> 12 = 12
01:58:15.506 -> 13 = 13
01:58:15.506 -> 14 = 14
01:58:15.506 -> 15 = 15
01:58:15.506 -> 16 = 16
01:58:15.506 -> 17 = 17
01:58:15.506 -> 18 = 18
01:58:15.506 -> 19 = 19
01:58:15.506 -> 20 = 20
01:58:15.506 -> 21 = 21
01:58:15.506 -> 22 = 22
01:58:15.506 -> 23 = 23
01:58:15.506 -> 24 = 24
01:58:15.506 -> 25 = 25
01:58:15.506 -> 26 = 26
01:58:15.506 -> 27 = 27
01:58:15.506 -> 28 = 28
01:58:15.506 -> 29 = 29
01:58:15.506 -> 30 = 30
01:58:15.506 -> 31 = 31
01:58:15.506 -> 32 = 32
01:58:15.506 -> 33 = 33
01:58:15.506 -> 34 = 34
01:58:15.506 -> 35 = 35
01:58:15.506 -> 36 = 36
01:58:15.506 -> 37 = 37
01:58:15.506 -> 38 = 38
01:58:15.506 -> 39 = 39
01:58:15.506 -> 40 = 40
01:58:15.506 -> 41 = 41
01:58:15.506 -> 42 = 42
01:58:15.506 -> 43 = 43
01:58:15.506 -> 44 = 44
01:58:15.506 -> 45 = 45
01:58:15.506 -> 46 = 46
01:58:15.506 -> 47 = 47
01:58:15.506 -> 48 = 48
01:58:15.506 -> 49 = 49
01:58:15.506 -> 50 = 50
01:58:15.506 -> 51 = 51
01:58:15.506 -> 52 = 52
01:58:15.506 -> 53 = 53
01:58:15.506 -> 54 = 54
01:58:15.506 -> 55 = 55
01:58:15.506 -> 56 = 56
01:58:15.506 -> 57 = 57
01:58:15.506 -> 58 = 58
01:58:15.506 -> 59 = 59
01:58:15.506 -> 60 = 60
01:58:15.506 -> 61 = 61
01:58:15.506 -> 62 = 62
01:58:15.506 -> 63 = 63
01:58:15.506 -> 64 = 64
01:58:15.506 -> 65 = 65
01:58:15.506 -> 66 = 66
01:58:15.506 -> 67 = 67
01:58:15.506 -> 68 = 68
01:58:15.506 -> 69 = 69
01:58:15.506 -> 70 = 70
01:58:15.506 -> 71 = 71
01:58:15.506 -> 72 = 72
01:58:15.506 -> 73 = 73
01:58:15.506 -> 74 = 74
01:58:15.506 -> 75 = 75
01:58:15.506 -> 76 = 76
01:58:15.506 -> 77 = 77
01:58:15.506 -> 78 = 78
01:58:15.506 -> 79 = 79
01:58:15.506 -> 80 = 80
01:58:15.506 -> 81 = 81
01:58:15.506 -> 82 = 82
01:58:15.506 -> 83 = 83
01:58:15.506 -> 84 = 84
01:58:15.506 -> 85 = 85
01:58:15.559 -> 86 = 86
01:58:15.559 -> 87 = 87
01:58:15.559 -> 88 = 88
01:58:15.559 -> 89 = 89
01:58:15.559 -> 90 = undefined
01:58:15.559 -> 91 = undefined
01:58:15.559 -> 92 = undefined
01:58:15.559 -> 93 = undefined
01:58:15.559 -> 94 = undefined
01:58:15.559 -> 95 = undefined
01:58:15.559 -> 96 = undefined
01:58:15.559 -> 97 = undefined
01:58:15.559 -> 98 = undefined
01:58:15.559 -> 99 = undefined
01:58:15.559 -> num89: 89
01:58:15.559 -> num90: undefined
01:58:15.559 -> num99: undefined
01:58:15.559 -> num100: 100
I want to have the feature of "goto". I will appreciate it if anybody can advice me how to do so?
Thank you!
Yang
Does elk accept minified code?
does elk need spaces etc. to be able to parse? also how does elk handle the original source after parsing it? I understand elk doesn't perform a bytecode step so how is everything handled in ram?
there is a limit (7 from my testing) of assignments allowed in a 'let ' statement. easy fix is to limit the number assignments per let ... but some minimizes will group everything into one 'let ' ... is this a limit or a bug?
Not Working
let a = 0, b = 0, c = 0, d = 5500, e = 45, f = 0, g = 0, h = 0, i = num();
Working
let a = 0, b = 0; let c = 5500, d = 0, e = 45, f = 0, g = 0, h = 0, i = num();
btw: num() would have been defined elsewhere in the code ...
LINUX_DIST="Linux Mint 18.3 Sylvia MATE 32-bit"
KERNEL=Linux computer 4.10.0-38-generic i686 i686 i686 GNU/Linux
ARDUINO IDE: 1.8.10 (32bit)
Elk Library: release 0.0.16 (Installed manually into Arduino IDE library folder)
ESP8266 BOARD: 2.5.2 (Installed with board manager from Arduino IDE)
Arduino Boards: 1.8.1 (Installed with board manager from Arduino IDE)
ESP32 Board: 1.0.4 (Installed with board manager from Arduino IDE)
Test Code
#include "elk.h" // Add Elk library
extern "C" void myDelay(int milli) {
delay(milli);
}
extern "C" void myWrite(int pin, int val) {
digitalWrite(pin, val);
}
extern "C" void myMode(int pin, int mode) {
pinMode(pin, mode);
}
struct js *js;
void setup() {
Serial.begin(115200);
Serial.println();
js = js_create(malloc(700), 700);
Serial.println("malloc done");
js_import(js, "delay", (uintptr_t) myDelay, "vi");
js_import(js, "digitalWrite", (uintptr_t) myWrite, "vii");
js_import(js, "pinMode", (uintptr_t) myMode, "vii");
Serial.println("imports done");
js_eval(js, "let pin = 2;", 0); // <--- HERE IS THE PROBLEM ON ESP8266 & AVR
js_eval(js, "pinMode(2, 1);", 0); // Set LED pin to OUTPUT mode ... on esp32 set to (pin, 2)
js_eval(js, "let loop = function() { delay(200); digitalWrite(2, 1); delay(200); digitalWrite(2, 0); };", 0);
Serial.println("ready ... looping");
}
void loop() {
js_eval(js, "loop();", 0);
Serial.println(" ... looping");
}
This functions as expected on the esp32 platform ... and when I eliminate the variable from the digitalWrite function calls and remark-out the "let pin = 2" js_eval call ... everything works as expected on the esp8266 & arv platforms ... so it's defiantly the "let pin = 2;" variable setting call that's causing things to bork on the esp8266 & avr platforms ...
UPDATE: on the avr platform it reboots ... on the esp8266 it ignores any js_evals after the "let pin = 2" call ... update update ... if I don't try to access the variable ... no reboot happens ... but still doesn't function ... just setting the variable causes it to fail ...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.