EzDevInfo.com

sweet.js

Sweeten your JavaScript. sweet.js

Generate dynamic comments with sweet.js

How can I transform the following snippet:

let myVar: string = 'test';

To following output:

// type {string}
var myVar = 'test';

using sweetjs?

UPDATE

I'm looking for a way to transform the exact first code snippet to the second one. Including the // type {string} comment.

I Want to use it to create a simple DSL to generate a code to be checked with google closure compiler.


Source: (StackOverflow)

Sweet.js - Parenthesis in macros body

I want to use parenthesis in macros body to group expressions. For example:

macro m {
  rule { ($x, $y) } => {
    $x >>> ($y * 5)
  }
}

Sweet.js remove all parenthesis:

m(6, 7) => 6 >>> 7 * 5

I expect next output:

m(6, 7) => 6 >>> (7 * 5)

How can I escape parenthesis inside macros body?


Source: (StackOverflow)

Advertisements

Match the end of a block with Sweet.js

I'm trying to write a case macro in sweet.js but I don't know how to match the end of a block. In particular I would like to match the code between the macro call and the end of the block that contains it. For example if my macro is myMacro, and the code is as follows

var foo = function() {
    console.log('log1');
    myMacro(someArg);
    console.log('log2');
    console.log('log3');
}        

I would like to be able to match the lines with 'log2' and 'log3'. My guess is that I can't but I can't find a clear definition how matching works in the documentation (pointers would be appreciated). Is it possible ?


Source: (StackOverflow)

Convert sweet.js argument into string

How would you create a string from an argument to a sweet.js macro? For example:

let foo = macro {
    rule {
        $name
    } => {
        console.log('$name', $name);
    }
}

var x = 42;

foo x

Will output:

console.log(x, x);

When I'd prefer it to output:

console.log('x', x);

So the first argument has quotes around it.


Source: (StackOverflow)

Sweet.js - Expand token as a string

I want to expand a token to a string. For example, I have this macro:

macro String {
  rule {
    $x
  } => {
    "$x"
  }
}

I would expect String 1 to expand to "1", however it expands to just 1;

How can I accomplish this?

EDIT: This seems imposible to do with a declarative approach, but should be possible with an imperative approach (see this comment):

macro String {
  case {_ $x } => {        
    return #{"$x"}
  }
}

But that still expands with quotes.


Source: (StackOverflow)

Javascript macro: implementing F# style forward pipe operator

I want to implement a higher order function (hof) that essentially works like F# style forward-pipe operator (passes a value as the first argument to another function, myFunc). The only way I can think of is this:

function hof(val, myFunc, args_array) {...}

where args_array is the array of arguments for the call to myFunc (excluding the first argument, since that's going to be val)

But this doesn't look very elegant to me. Is there a better way to do this?

Edit: I found this on github https://gist.github.com/aaronpowell/d5ffaf78666f2b8fb033. But I don't really understand what the sweet.js code is doing. It'd be very helpful if you could annotate the code, specifically:

case infix { $val | _ $fn($args (,) ...) } => {
    return #{
        ($fn.length <= [$args (,) ...].length + 1 ? $fn($args (,) ..., $val) : $fn.bind(null, $args (,) ..., $val))
    }
}

case infix { $val | _ $fn } => {
    return #{
        ($fn.length <= 1 ? $fn($val) : $fn.bind(null, $val))
    }
}

Source: (StackOverflow)

Lazy evaluation macro with Sweet.js

I just got in JavaScript and noticed that lazy evaluation is not directly supported in this language. Natively the code turns into the hell of boiler plate like this:

function lazy(f) {
    var v = undefined;
    return function() {
        if (v == undefined) 
            v = f();
        return v;
    }
}

// 10 times larger than actual operation
var foo = lazy(function() {
    return 3 + 3;
});

But I found Sweet.js and believe that it can make the code simple like this:

var foo = lazy (3 + 3);

var goo = lazy {
    var a = 3 + 3;
    return a;
};

So I tested out Edit Sweet.js:

function lazy_f(f) {
    var v = undefined;
    return function() {
        if (v == undefined) 
            v = f();
        return v;
    }
}

macro lazy {
    rules { $expr } => {
        lazy_f(function() { return $expr; })
    }
}

var foo = lazy (3 + 3);

It worked with a single expr. But there are cases that lazy takes in a block of expr like this:

var goo = lazy {
    var a = 3 + 3;
    return a;
};

So I arranged the above code like this:

function lazy_f(f) {
    var v = undefined;
    return function() {
        if (v == undefined) 
            v = f();
        return v;
    }
}

macro lazy {
    rule { $($expr) (;) ... } => {     //
        lazy_f(function() $expr ...);  //
    }                                  //
    rules { $expr } => {
        lazy_f(function() { return $expr; })
    }
}

var foo = lazy (3 + 3);

var goo = lazy {
    var a = 3 + 3;
    return a;
};

And it doesn't work for some reason. I believe the first pattern $($expr) (;) ... shouldn't match with (3 + 3), but apparently it's doing.

I worked on this for an hour and finally gave up. How do you make the two patterns working at the same time?

If it's not possible to do so, I would like to take another way for a single expr:

lar foo = 3 + 3;
var foo_content = foo();

And I don't know how to do this as well.


Source: (StackOverflow)

is it possible to create a sweetjs macro making multiline strings possible in javascript?

I am really new to sweet.js.

I would love to have multiline strings in javascript just like in EcmaScript 6:

var htmlString = `Say hello to 
multi-line
strings!`;

Is it possible to formulate a sweetjs macro handling that (and how ??) ?

Furthermore, would it be possible to do String Interpolation/Templating using that macro just like ES6 does ?


Source: (StackOverflow)

Sweet.js - How to put variable in identifier name and string variable?

I'm brand new to Sweet.js. My first simple macro is the following

macro test {
  rule {
    $className($entityName)
  } => {
    function test$className()
    {
      console.print("$className");
      console.print("$entityName");
    }
  }
}

test me(More)

which produces

function test$className() {
    console.print(me);
    console.print(More);
}

but I'd like it to produce this:

function testMe() {
    console.print("me");
    console.print("More");
}

but any variants I've tried for it haven't worked. Any suggestions?


Source: (StackOverflow)

How to break SweetJS hygiene for local variable?

I am attempting to use SweetJS in my project. In order to better understand and learn SweetJS I thought I would start with a simple "class" macro (I know a few exist, just playing around here...). I can NOT seem to get SweetJS to stop messing with my local variables "self" and "superCall" however. Any ideas what I am doing wrong? I would like var self=this to 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 you can see, var self=this has been turned into var self$2 = this. How can I prevent this? I have attempted to use makeIdent, but I think I am doing something wrong. Any ideas? Thanks!


Source: (StackOverflow)

Sweet.js macro that calls a method

I'm trying to write a sweet.js macro which needs to generate method call syntax, obj.method(), but the method is passed in to the macro as a literal expression. For example:

mcall(obj, toString().length);
// becomes
obj.toString().length;

I've got something that's close:

macro mcall {
  rule { ($o, $m:expr) } => { $o.$m }
}

mcall(obj, toString().length);

However, this apparently expands to this:

obj . ( toString ( ) . length );

Where are these extra parentheses coming from, and how do I get rid of them? Should I be using case rules and #{}? I tried permutations of that but still couldn't succeed at generating a method call without extra parentheses.


Source: (StackOverflow)

Implement multiline skinny arrow syntax in sweetjs

I'm playing around with sweetjs and for the life of me can't figure out why this rule for parameterless multiline skinny arrow syntax isn't matched

Code:

macro -> {
  rule infix { () | { $body ... $last:expr } } => {
    function( ) { 
      $body ...;
      return $last
    }
  }
}

var fn = () -> {
  var a = 1;
  a + 2;
};
expect(fn()).to.equal(3);

results in

SyntaxError: [macro] Macro `-` could not be matched with `> {} ; expect ()...`
10: var fn = () -> {
                ^

Source: (StackOverflow)

Sweet.js: macro that targets variables before the tokens?

One of the items on my TODO list is creating a fun coding language that 'compiles' to JavaScript. I would like to try out Sweet.js for this, but I'm wondering if it is possible to write a rule that targets keywords that are before the rule?

As an example, let's say you'd want to create a Yoda-styled JavaScript. A source line could look like this:

six var is;

Would be mapped to

var six;

Is this possible using Sweet.js?


Source: (StackOverflow)

Compile SweetJS to String in Node.js

From the shell, I can call the Sweet.js compiler.

sjs -m macro-providing-module -o output-directory/file.js input-directory/file.sjs

How can I do the same from inside a Node.js module such that instead of outputting to a specified file, I get the compiled output as a string?

var sweetjs = require('sweet.js');
var input = require('fs').readSync('input-directory/file.sjs');
var module = 'macro-providing-module';

var output = sweetjs(/* ??? */);

Source: (StackOverflow)

How to create a parameterized infix macro in sweet.js

In the bluebird wiki article about JavaScript optimization killers, the author mentions that passing the arguments keyword to any function (except apply) will cause the parent function to not be optimizable. I would like to create a sweet.js macro that allows me to write standard idiomatic JavaScript but will take care of the optimization killer.

Ideally, I would like a macro that would take the following function:

function foo() {
    var args = [].slice.call(arguments);
    return args;
}

And output something like this:

function foo() {
    var args = [];
    for(var i, len = arguments.length; i < len; i++) {
        args.push(arguments[i]);
    }
    return args;
}

I am having trouble with getting the sweet.js macro syntax correct, however. This is what I have so far:

example.sjs

let arguments = macro {
    rule infix {
         [].slice.call | 
    } => {
        [];
        for(var i = 0, len = arguments.length; i < len; i++) {
            args.push(arguments[i])
        }
    }
}

function toArray() {
    var args = [].slice.call  arguments
    return args;
}

Which outputs the following:

function toArray() {
    var args$2 = [];
    for (var i = 0, len = arguments.length; i < len; i++) {
        args.push(arguments[i]);
    }
    return args$2;
}

I tried making my macro have parenthesis around the arguments keyword and also include the var declaration, but without any success. I tried something like this:

invalid macro

let arguments = macro {
    rule infix {
        var $var = [].slice.call ( | ) 
    } => {
        var $var = [];
        for(var i = 0, len = arguments.length; i < len; i++) {
            args.push(arguments[i])
        }
    }
}

This produces the following error:

SyntaxError: [syntaxCase] Infix macros require a `|` separator
414: 
                                ^

Source: (StackOverflow)