Hello World
Spiga

增强Jscex目标代码可调试性:已包含输入代码

2012-02-16 23:30 by 老赵, 1405 visits

我们先来看一段Jscex生成的目标代码,您能看出其输入代码是什么样的吗?

target code without source

其实这段代码的原始输入是排序算法动画中“快速排序”的Partition方法:

function (array, begin, end) {
    var i = begin;
    var j = end;
    var pivot = array[Math.floor((begin + end) / 2)];

    while (i <= j) {
        while (true) {
            var r = $await(compareAsync(array[i], pivot));
            if (r < 0) { i++; } else { break; }
        }

        while (true) {
            var r = $await(compareAsync(array[j], pivot));
            if (r > 0) { j--; } else { break; }
        }

        if (i <= j) {
            $await(swapAsync(array, i, j));
            i++;
            j--;
        }
    }

    return i;
}

是不是显得比较繁琐?但其实Jscex生成代码的模式很简单,您只要忽视Combine,Delay等辅助方法,剩下的代码几乎都跟原始代码一一对应了。不过用肉眼来识别原始代码多少还是需要些脑力,于是即将发布的0.6.0版Jscex编译器便直接在目标代码的左侧生成对应的原始代码了:

target code with source

当然左侧原始代码并非与您输入的完全一致,它毕竟也是经过解析和重新生成的结果,并需要与目标代码逐行对应,多少会有些格式上的改变,但此时您想设置断点也好,调试也罢,只要把注意力更多放在左侧的输入代码上,而不用肉眼去识别相对复杂的Monad代码了。

当然,复杂和简单总是相对的,Jscex的目标代码虽然比输入要复杂许多,但至少还能辨别出原始代码,也能通过肉眼识别给转化回去。如果您观察Jscex的同类产品streamline.js的话,就会发现它的目标代码真是如天书一般:

streamlined

这是因为streamline.js则使用了传统的状态机展开,Jscex使用的是Monad生成方式,其主要目的之一便是考虑到目标代码的可读性。Jscex是基于成熟理论,并经过精心设计的类库,并没有很多人想象中的那么多问题。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

12 条回复

  1. sheldonw
    123.139.122.*
    链接

    sheldonw 2012-02-17 00:03:26

    有了这个东西可以很方便调试了,说了句废话,支持老赵。

  2. 老赵
    admin
    链接

    老赵 2012-02-17 00:10:33

    @sheldonw

    多谢,目标代码生成还是有些许进步空间,要逐渐改进。

  3. zc
    65.100.229.*
    链接

    zc 2012-02-17 08:59:31

    eval哪去了?

  4. 老赵
    admin
    链接

    老赵 2012-02-17 10:22:48

    @zc

    eval是使用时的代码,现在是展示最终生成的代码,当然没有eval。

  5. 银光小子
    113.116.26.*
    链接

    银光小子 2012-02-17 20:26:22

    呵呵,要是明年很多公司的招聘上写
    熟练掌握JavaScript,掌握Jscex尤佳....

    就好了 哈哈

  6. 老赵
    admin
    链接

    老赵 2012-02-17 23:20:52

    @银光小子

    托您吉言,这样最好了,活活。

  7. tu
    202.133.226.*
    链接

    tu 2012-05-24 16:28:20

    老赵,你的Jscex不支持forEach,例如:

    var printAsync = eval(Jscex.compile('async', function(x) {
    
        console.log(x);
    
    }));
    
    
    eval(Jscex.compile('async', function() {
    
        [1,2].forEach(function(x){
            $await(printAsync(x));
            //console.log(x);
        });
    
    }))().start();
    
  8. 老赵
    admin
    链接

    老赵 2012-05-24 22:02:59

    @tu

    不是不支持forEach,而是你forEach里面是另一个函数了,自然不支持。记住一点,就是$await只能“直接”用在eval(Jscex.compile())的函数内部。

  9. tu
    202.133.226.*
    链接

    tu 2012-05-25 15:20:58

    喔,明白了,那么下面这种情况呢?

    var printAsync = eval(Jscex.compile('async', function(x) {
        console.log(x);
    }));
    
    var trueAsync = eval(Jscex.compile('async', function() {
        return true;
    }));
    
    eval(Jscex.compile('async', function() {
        $await(printAsync($await(trueAsync())? true:false));
    }))().start();
    
  10. 老赵
    admin
    链接

    老赵 2012-05-25 21:11:55

    @tu

    这是不支持的,目前$await没法嵌套,只能以下几种情况:

    return $await(...);
    
    $await(...);
    
    var a = $await(...);
    
    a = $await(...);
    

    算是Jscex目前的缺陷吧。

  11. tu
    202.133.226.*
    链接

    tu 2012-05-26 08:53:35

    虽然有这样的小问题,Jscex还是不错的,编写的代码易读,也节约很多代码量,

    不知道Jscex能否给出更清晰的出错代码描述不?相对于普通Js开发,Jscex的调试排错略微不方便些

  12. 老赵
    admin
    链接

    老赵 2012-05-26 10:16:18

    @tu

    的确有这个问题,还在想办法,例如在生成代码旁边增加输入代码。主要是JavaScript不支持source map所以这种以JavaScript作为编译目标的语言(例如CoffeeScript)都有类似问题……

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我