2

我正在尝试在我的项目中使用 SweetJS。为了更好地理解和学习 SweetJS,我想我会从一个简单的“类”宏开始(我知道存在一些,只是在这里玩......)。但是,我似乎无法让 SweetJS 停止弄乱我的局部变量“self”和“superCall”。任何想法我做错了什么?我想var self=this留下var self=this来而不是被破坏。

macro class {
  case { _ $name extends $parent {
    constructor $cargs { $cbody ... }
    $($mname $margs { $mbody ... } ) ... 
  } } => {
    return #{
        function $name $cargs { var self=this,superCall=$parent.prototype; $cbody ... }
        $name.prototype = Object.create($parent.prototype);
        ($name.prototype.$mname = function $margs {var self=this,superCall=$parent.prototype; $mbody ... } ) ...;
    }
  }

  case { _ $name { $body ...} } => {
    return #{ class $name extends test2 { $body ... } };
  }
}

macro super {
    case { $macroName.$name( $($args (,) ...) ) } => {
       letstx $s = [makeIdent("self", #{ $macroName })];
       letstx $sC = [makeIdent("superCall", #{ $macroName })];
       return #{
          $sC.$name.call($s)
       };
    }

    case { $macroName( $args ... ) } => {
       letstx $s = [makeIdent("self", #{ $macroName })];
       letstx $sC = [makeIdent("superCall", #{ $macroName })];
       return #{
          superCall.constructor.call($s);
       };
    }
}

class test extends cow {
 constructor(arg1, arg2) {
     console.log('Hello world!');
 }
 method1(arg1, arg2) {
     super.method1();
 }
}

这扩展为:

function test(arg1, arg2) {
    var self$2 = this, superCall$2 = cow.prototype;
    console.log('Hello world!');
}
test.prototype = Object.create(cow.prototype);
test.prototype.method1 = function (arg1, arg2) {
    var self$2 = this, superCall$2 = cow.prototype;
    superCall.method1.call(self);
};

如您所见,var self=this已变成var self$2 = this. 我怎样才能防止这种情况?我曾尝试使用makeIdent,但我认为我做错了什么。有任何想法吗?谢谢!

4

1 回答 1

2

为了打破卫生,您需要提供在您所在的宏范围之外的词法上下文。在这种情况下,通过使用$name绑定,您实际上是在宏之外而不是从内部引用范围;在这种情况下,这使得打破卫生成为可能。

结果,以下似乎有效:

macro class {
  case { _ $name extends $parent {
    constructor $cargs { $cbody ... }
    $($mname $margs { $mbody ... } ) ... 
  } } => {
    letstx $self = [makeIdent("self", #{ $name })];
    return #{
        function $name $cargs { var $self=this,superCall=$parent.prototype; $cbody ... }
        $name.prototype = Object.create($parent.prototype);
        ($name.prototype.$mname = function $margs {var $self=this,superCall=$parent.prototype; $mbody ... } ) ...;
    }
  }

  case { _ $name { $body ...} } => {
    return #{ class $name extends test2 { $body ... } };
  }
}

请注意,我创建了一个名为的标识符$self,并将类的名称用作我的语法对象。

在这里阅读更多关于打破卫生的信息。

于 2015-07-30T02:08:27.473 回答