javascriptsyntaxextending

How to extend Javascript with new while statment


I am trying to create a new way of implementing loops in Javascript. The user would type

Loop(n)
{
// code to repeat
}

and the new loop function would repeat the code inside the curly brackets 'n' times. It would simply implement a while loop in the back end with a counter variable.

I know how to create prototype functions, but I need more than passing in parameters to a function. I want the loop(n) statement to repeat a block of code specified by the coder.

I've had a look at Sweet.js, but there doesn't seem to be any references to doing what I am proposing.

How would I go about doing this?


Solution

  • The Sweet.js documentation does indeed have an example you can apply to looping. Here's a simple version:

    syntax loop = function (ctx) {
        const count = ctx.next().value;
        const code = ctx.next().value;
        return #`for (let __n = 0; __n < ${count}; ++__n) ${code}`;
    }
    

    ...though there's probably a better way to create the loop variable.

    You'd use that like this:

    loop 10 {
        // ...your code here...
    }
    

    Try it out here

    I'd probably want to specify the identifier to use for the counter:

    syntax loop = function (ctx) {
        const count = ctx.next().value;
        const identifier = ctx.next().value;
        const code = ctx.next().value;
        return #`for (let ${identifier} = 0; ${identifier} < ${count}; ++${identifier}) ${code}`;
    }
    

    Then:

    loop 10 index {
        console.log(index);
    }
    

    Try it out here

    I expect there's a way to make the identifier optional if you like.


    That said, I'd just use a function you pass a callback to:

    function loop(end, callback) {
        for (let n = 0; n < end; ++n) {
            callback(n);
        }
    }
    
    loop(10, n => console.log(n));
    .as-console-wrapper {
      max-height: 100% !important;
    }

    You can make that more feature-full quite easily:

    function loop(end, start, step, callback) {
        if (typeof end !== "number") {
            throw new Error("'end' should be a number");
        }
        if (typeof start === "function") {
            callback = start;
            start = 0;
            step = 1;
        } else if (typeof step === "function") {
            callback = step;
            step = 1;
        }
        if (typeof start !== "number") {
            throw new Error("'start' should be a number");
        }
        if (typeof step !== "number") {
            throw new Error("'step' should be a number");
        }
        for (let n = start; n < end; n += step) {
            callback(n);
        }
    }
    
    console.log("loop(3, n => console.log(n));");
    loop(3, n => console.log(n));
    console.log("loop(3, 1, n => console.log(n));");
    loop(3, 1, n => console.log(n));
    console.log("loop(6, 0, 2, n => console.log(n));");
    loop(6, 0, 2, n => console.log(n));
    .as-console-wrapper {
      max-height: 100% !important;
    }