在受控环境中将代码映射到JavaScript

时间:2017-03-15 18:48:15

标签: javascript parsing dsl transpiler

所以我有一个转换为javascript的DSL语言,但有一个问题,每次运行一个函数时,必须将控件赋予执行环境,该环境将决定是否运行该函数,跳过它,或者终止整个程序。例如,语言中的一段代码可能如下所示。

y = 2*r
value = draw(y)
r = 2

这会转化为类似的东西(可读性增加):

(function(){
    ASSIGN(["y"], MUL(NUMBER(2), VAR(["r"])));
    ASSIGN(["value"], CALL(["draw"],[VAR(["y"])]));
    ASSIGN(["r"], NUMBER(2));
})

现在问题是draw是一个异步函数,它需要时间来绘制这个东西,但javascript会立即执行那些东西,但我不想,并且阻止整个线程没有看起来是个好主意。

我想的解决方案是使用发电机,如果我没有弄错他们的用法

(function* (){
    yield START();
    ASSIGN(["y"], MUL(NUMBER(2), VAR(["r"])));
    ASSIGN(["value"], yield CALL(["draw"],[VAR(["y"])]) );
    ASSIGN(["r"], NUMBER(2));
    yield DONE();
})

因此执行环境的控制权为:

let app = myApp();
//process does the async stuff
let executor = new Executor(app);
executor.run();

class Executor {
    constructor(app){
        this.app = app;
        this.next();
    }
    next(value){
        this.process(this.app.next(value), this.next);
    }
    process(function_statment, resume){
        //Do the async stuff here
        resume('value');
    }
}

美丽:3

然而,这并不是当前浏览器最兼容的方法,显然生成器并未得到广泛支持。

作为我的最后一招,我会使用。

(function (EENV){
    EENV(START(),function(){
        ASSIGN(["y"], MUL(NUMBER(2), VAR(["r"])));
        EENV(CALL(["draw"],[VAR(["y"])]), function(value){
           ASSIGN(["value"], value);
           ASSIGN(["r"], NUMBER(2));
           EENV(DONE(),function(){});
        });
    });
})

但是这种方式更难以理解,即使我使用了事件,它仍然会那样,这将使调试转换器变得困难(检查代码,执行单元测试等等)因为它正在制造这样的回调地狱。

执行环境就像。

myApp(function(statment, callback){
   //DO ASYNC STUFF
   callback(someValue);
});

您有其他解决方案或想法吗?希望与收益率类似?

0 个答案:

没有答案