javascript - How to break SweetJS hygiene for local variable? -
i attempting use sweetjs in project. in order better understand , learn sweetjs thought start simple "class" macro (i know few exist, playing around here...). can not seem sweetjs stop messing local variables "self" , "supercall" however. ideas doing wrong? var self=this
remain var self=this
instead of being mangled.
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(); } }
this expands to:
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); };
as can see, var self=this
has been turned var self$2 = this
. how can prevent this? have attempted use makeident
, think doing wrong. ideas? thanks!
in order break hygiene need provide lexical context outside scope of macro in. in case, using $name
binding, referencing scope outside of macro rather within; makes breaking hygiene possible in case.
as result, following seems work:
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 ... } }; } }
notice created identifier named $self
, used name of class syntax object.
read more breaking hygiene here.
Comments
Post a Comment