COMMUNITY

Hscript serialization

Hello i Need to expose hscript in an api. I want that an user can run commands hscript from an api with the state of programm hscript serialized between a request and another. What Is the best mode forse serialize the state of a hscript program?

I’m pretty sure Terry Cavanaugh worked on some of these issues wrt hscript (async behavior, etc.) – I thought he had a repo, but I can’t find it just now.

Anyway, one of the difficulties of serializing hscript state is that functions can be part of the state. It wouldn’t be impossible to figure out how to serialize these functions… hscript also has a number of forks – there could be something interesting there: https://github.com/HaxeFoundation/hscript/network/members

Another difficulty is that hscript isn’t really designed for as a REPL (execute one instruction at a time.) But you can make it that way. (ihx is a fun little project, ala irb, that is an interactive haxe repl. They chose to re-execute every instruction every time – not great if the instructions have side affects, like appending to a file, or grabbing a timestamp.)

Another way is to use the private interp.exprReturn function instead of the interp.execute function. Then you could try serializing / deserializing the “state of the interpreter” by storing the “locals” map. (sample below – note that .locals and /exprReturn both require @:privateAccess - aka, subject to breakage.)

This seems to work for simple state / values (as long as there are no functions involved). I’ll have to think a bit on solving for functions – it sounds like an interesting problem. :smiley:

import hscript.*;

class Test {

  public static function main()
  {
    var interp = new hscript.Interp();

    function exec_next_expr(e:String) {
      var parser = new hscript.Parser();
      var ast = parser.parseString(e);

      var result:Dynamic = @:privateAccess interp.exprReturn(ast);

      return result;
    }

    exec_next_expr('var x=4;');
    exec_next_expr('x = 1 + 2*x');
    trace(exec_next_expr('x'));

    // serializing the state, then, is equivalent to "storing the locals"
    var state0:String = @:privateAccess haxe.Serializer.run(interp.locals);

    // Now let's change x for the fun of it
    exec_next_expr('x = 5000;');
    trace(exec_next_expr('x'));

    // Now let's restore the locals
    @:privateAccess interp.locals = haxe.Unserializer.run(state0);
    
    trace('Restored x:');
    trace(exec_next_expr('x'));

    exec_next_expr('var x=4;');
  }
}

Run with:

> haxe -x Test -lib hscript
Test.hx:20: 9
Test.hx:27: 5000
Test.hx:32: Restored x:
Test.hx:33: 9
1 Like

thanks,
but the idea is storing only variables. i will inject the function on startup of the script. i could try also with override of get set and call functions