如何打破局部变量的 SweetJS 卫生?
How to break SweetJS hygiene for local variable?
我正在尝试在我的项目中使用 SweetJS。为了更好地理解和学习 SweetJS,我想我会从一个简单的 "class" 宏开始(我知道有一些存在,只是在这里玩玩......)。然而,我似乎无法让 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 = this, superCall = cow.prototype;
console.log('Hello world!');
}
test.prototype = Object.create(cow.prototype);
test.prototype.method1 = function (arg1, arg2) {
var self = this, superCall = cow.prototype;
superCall.method1.call(self);
};
如你所见,var self=this
已经变成了var self = this
。我怎样才能防止这种情况发生?我曾尝试使用 makeIdent
,但我认为我做错了什么。有任何想法吗?谢谢!
为了打破卫生,你需要提供你所在的宏范围之外的词法上下文。在这种情况下,通过使用 $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
的标识符,并使用 class 的名称作为我的语法对象。
阅读更多关于破坏卫生的内容here。
我正在尝试在我的项目中使用 SweetJS。为了更好地理解和学习 SweetJS,我想我会从一个简单的 "class" 宏开始(我知道有一些存在,只是在这里玩玩......)。然而,我似乎无法让 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 = this, superCall = cow.prototype;
console.log('Hello world!');
}
test.prototype = Object.create(cow.prototype);
test.prototype.method1 = function (arg1, arg2) {
var self = this, superCall = cow.prototype;
superCall.method1.call(self);
};
如你所见,var self=this
已经变成了var self = this
。我怎样才能防止这种情况发生?我曾尝试使用 makeIdent
,但我认为我做错了什么。有任何想法吗?谢谢!
为了打破卫生,你需要提供你所在的宏范围之外的词法上下文。在这种情况下,通过使用 $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
的标识符,并使用 class 的名称作为我的语法对象。
阅读更多关于破坏卫生的内容here。