npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jetblack/operator-overloading

v0.2.0

Published

A babel plugin for operator overloading

Downloads

46

Readme

@jetblack/operator-overloading

A Babel plugin for operator overloading.

There is a trivial template project here.

This was based on an idea by Benjamin Fox

There are a number of great implementations of operator overloading including a current proposal. This proposal is far more sophisticated than this implementation, but I had issues with my use case. This is a very simple version that worked for me and might be a good work-around for you while we wait for the proposal to be accepted.

Example

The following code adds two integers and then two points.

The directive at the start is required to enable the transformation.

'operator-overloading enabled'

class Point {

    constructor(x, y) {
        this.x = x
        this.y = y
    }
    
    [Symbol.for('+')](other) {
        const x = this.x + other.x
        const y = this.y + other.y
        return new Point(x, y)
    }
}

// Built in operators still work.
const x1 = 2
const x2 = 3
const x3 = x1 + x2
console.log(x3)

// Overridden operators work!
const p1 = new Point(5, 5)
const p2 = new Point(2, 3)
const p3 = p1 + p2
console.log(p3)

produces the following output:

5
Point { x: 7, y: 8 }

Status

This is the first babel plugin I have written, so your mileage may vary.

I would appreciate any help!

Usage

  1. Make a new folder and create a package.json file.
~$ mkdir my-app
~$ cd my-app
~/my-app$ npm init -y
  1. Install babel and the basic preset (also @babel/cli for easier testing).
~/my-app$ npm install --save-dev @babel/core @babel/preset-env @babel/cli
  1. Install the operator overload plugin. Note that "node": "current" is specified in targets. The targets specified must support arrow functions.
~/my-app$ npm install --save-dev @jetblack/operator-overloading
  1. Create a .babelrc file:
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets" : {
                    "node": "current"
                }
            }
        ]
    ],
    "plugins": ["module:@jetblack/operator-overloading"]
}
  1. Write some code:
'operator-overloading enabled'

class Point {

    constructor(x, y) {
        this.x = x
        this.y = y
    }
    
    [Symbol.for('+')](other) {
        const x = this.x + other.x
        const y = this.y + other.y
        return new Point(x, y)
    }
}

const p1 = new Point(5, 5)
const p2 = new Point(2, 3)
const p3 = p1 + p2
console.log(p3)
  1. Run it with babel-node:
~/my-app$ ./node_modules/.bin/babel-node.cmd index.js
Point { x: 7, y: 8 }

Description

The plugin wraps expressions in arrow functions. The following is produced for x + y.

(() => {
  'operator-overloading disabled';

  return x !== undefined && x !== null && x[Symbol.for("+")]
    ? x[Symbol.for("+")](y)
    : x + y;
})()

For example the following code:

let x = 1, y = 2
let z = x + y

gets re-written as:

let x = 1, y = 2
let z = (() => {
  return x !== undefined && x !== null && x[Symbol.for("+")]
    ? x[Symbol.for("+")](y)
    : x + y;
})();

This allows the creation of custom overrides such as:

class Point {

    constructor(x, y) {
        this.x = x
        this.y = y
    }
    
    [Symbol.For('+')](other) {
        const x = this.x + other.x
        const y = this.y + other.y
        return new Point(x, y)
    }
}

Options

As the plugin requires arrow functions the @babel/preset-env preset targets must support them.

Operator overloading is disabled for all files by default.

This can be enabled globally in the .babelrc:

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets" : {
                    "node": "current"
                }
            }
        ]
    ],
    "plugins": [
        [
            "@jetblack/operator-overloading",
            {
                "enabled": true
            }
        ]
    ]
}

It can be enabled or disabled locally by including the 'operator-overloading' directive at the start of a file or within a block.

'operator-overloading disabled'
let a = 1
let b = 2
let c = a + b

'operator-overloading enabled'
let x = Point(2, 4)
let y = Point(3, 5)
let z = x + y

Using operator overloading transpilation will increase compilation and run time when enabled.

Unsupported operations

No transpilation will be applied to he following operators.

  • typeof
  • ===
  • !==
  • &&
  • ||
  • instanceof

Supported operations

Arithmetic

  • + addition [Symbol.for('+')](other)
  • - subtraction [Symbol.for('-')](other)
  • * multiplication [Symbol.for('*')](other)
  • / division [Symbol.for('/')](other)
  • % remainder [Symbol.for('%')](other)

Arithmetic Unary

  • +: plus [Symbol.for('plus')]()
  • -: minus [Symbol.for('minus')]()

Increment an Decrement

  • ++ increment [Symbol.for('prefix-increment')]() and [Symbol.for('postfix-increment')]()
  • -- decrement [Symbol.for('prefix-decrement')]() and [Symbol.for('postfix-decrement')]()

Arithmetic Assignment

Arithmetic assignment reuses the overrides for arithmetic.

  • += addition assignment [Symbol.for('+')](other)
  • -= subtraction assignment [Symbol.for('-')](other)
  • *= multiplication assignment [Symbol.for('*')](other)
  • /= division assignment [Symbol.for('/')](other)
  • %= remainder assignment [Symbol.for('%')](other)

Bitwise

  • & bitwise and [Symbol.for('&')](other)
  • | bitwise or [Symbol.for('|')](other)
  • ~ bitwise not [Symbol.for('~')]()
  • ^ bitwise xor [Symbol.for('^')](other)
  • << bitwise shift left [Symbol.for('<<')](other)
  • >> bitwise sign propagating shift right [Symbol.for('>>')](other)
  • >>> bitwise zero padding shift right [Symbol.for('>>>')](other)

Bitwise Assignment

Bitwise assignment reuses the overrides for bitwise.

  • &= bitwise and [Symbol.for('&')](other)
  • |= bitwise or [Symbol.for('|')](other)
  • ~= bitwise not [Symbol.for('~')]()
  • ^= bitwise xor [Symbol.for('^')](other)
  • <<= bitwise shift left [Symbol.for('<<')](other)
  • >>= bitwise sign propagating shift right [Symbol.for('>>')](other)
  • >>>= bitwise zero padding shift right [Symbol.for('>>>')](other)

Others

  • delete delete property [Symbol.for('delete')](key)
  • in has property [Symbol.for('in')](key)