Giter VIP home page Giter VIP logo

elk's People

Contributors

cpq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elk's Issues

Some problems with displacement operations

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!!!

request: add define to elk.h for library version

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"

ESP32 under the Arduino IDE does not work ...

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

limited (seven) number of assignments in 'let' statements

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 ...

internal fault

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

WebAssembly

Would you consider releasing a WebAssembly version of elk? For the purpose of testing Elk code from within a web browser based editor.

Quickly running out of memory in while loop

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

How to js_str a longger float value?

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

the logical NOT (!) operator is not working ...

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

use of return from within a function causes irregular results ...

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);}
  }    
};

Bitwise AND operator

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);

ERROR: bad sig when using space in function declaration

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)

ESP8266 under the Arduino IDE does not work

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 ...

Minify code?

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?

AVR support

are there any future plans to release the binary blob for the AVR platform?

Why compaction instead of regular mark&sweep?

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?

unit_test.c is out of sync with the rest of the code development ...

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"));

Question: Elk's GPLv2 license and binary firmware distribution?

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.

Note the confusion with `elk stack`

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!

Garbage collection doesn't fixup object references to upper and deletes used entities from memory.

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....

bad parsing numbers beginning by 9 (ESP32)

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

Question how to write on MCP23017

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...

AVR under the Arduino IDE does not work

continued from issue #4

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

The public API should allow creating an object

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));

'equal' & 'not equal' is not working ...

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

string end with random character

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.

No longer compiles on esp32

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

Timer function makes esp32 reboot.

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

`

missing type check for --/++ causes js.mem corruption

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).

Bug

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; }.

Example

#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;

Fix suggestion

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");

Fails to compile under the Arduino IDE

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 ...

ESP8266 support

Are there any plans to release the binary blob for the ESP8266 platform?

0.0.17 breaks nested while loops on the esp32 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.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);

Question: About variables

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;
}

Question: redefining in elk

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

compile fails

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

ESP8266 Fails to compile under the Arduino IDE

continued from issue #4

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 ...

calculated function parameters are being processed out of order

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);

Grammer mistakes not report in "while" loop

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

ESP8266 & AVR under the Arduino IDE fails when setting a variable

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 ...

js_destroy()

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);

Compile on ubuntu linux fails ...

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 ...

Cannot make simple program work

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.