Created
April 16, 2019 05:23
-
-
Save IanSSenne/7f281123e4d74c0eca8196df849b4ab9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const esprima = require("esprima"); | |
const escodegen = require("escodegen"); | |
const fs = require("fs"); | |
const minify = require("terser"); | |
const content = fs.readFileSync("./build.ts.js", "utf8"); | |
const wrapper = fs.readFileSync("./builder/require.js", "utf8"); | |
let ast = esprima.parseScript(content); | |
function walk(o, cb) { | |
if (o.type) { | |
o = cb(o); | |
} | |
for (let key in o) { | |
let v = o[key]; | |
if (!v) continue; | |
if (v.constructor === Object || v.type) { | |
o[key] = walk(v, cb); | |
} else if (v.constructor === Array) { | |
for (let i = 0; i < v.length; i++) { | |
o[key][i] = walk(v[i], cb); | |
} | |
} | |
} | |
return o; | |
} | |
var names = { | |
'+': "PLUS", | |
'-': "MINUS", | |
'*': "MULTIPLY", | |
'/': "DIVIDE", | |
'%': "MOD", | |
'**': "EXPONENTIATION", | |
'^': "XOR", | |
'&': "AND", | |
'==': "EQUAL", | |
'!=': "NOTEQUAL", | |
'===': "STRICTEQUAL", | |
'!==': "STRICTNOTEQUAL", | |
'<': "LESSTHAN", | |
'>': "GREATERTHAN", | |
'<=': "LESSTHANEQUAL", | |
">=": "GREATERTHANEQUAL", | |
'<<': "LEFTSHIFT", | |
'>>': "RIGHTSHIFT", | |
'>>>': "UNSIGNEDRIGHTSHIFT", | |
"|": "OR" | |
}; | |
let r = ""; | |
for (let i in names) { | |
r += `${names[i]}(a,b){return a ${i} b;}\n`; | |
} | |
// fs.writeFileSync("overrides_template_autogenerated.js", r); | |
ast = walk(ast, function (node) { | |
if (node.type === "BinaryExpression") { | |
if (names[node.operator]) { | |
node.type = "CallExpression"; | |
node.arguments = [node.left, node.right]; | |
node.callee = { | |
"type": "MemberExpression", | |
"computed": false, | |
"object": { | |
"type": "MemberExpression", | |
"computed": false, | |
"object": { | |
"type": "Identifier", | |
"name": "_modules" | |
}, | |
"property": { | |
"type": "Identifier", | |
"name": "overloads" | |
} | |
}, | |
"property": { | |
"type": "Identifier", | |
"name": names[node.operator] | |
} | |
}; | |
} | |
} | |
return node; | |
}); | |
let intermediate = wrapper.replace("/*%overloads%*/", JSON.stringify(names)).replace("/*%content%*/", escodegen.generate(ast, { | |
parse: (...args) => JSON.parse(args[0]).constructor.name + "(" + args[0] + ")" | |
})); | |
fs.writeFileSync("build.temp.js", intermediate); | |
fs.writeFileSync("build.out.js", minify.minify(intermediate).code); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
function factory(name, op) { | |
let work = new Function("a", "b", "return a" + op + "b"); | |
return (a, b) => { | |
let cons = a.constructor; | |
if (cons.overloads && cons.overloads[name]) { | |
return cons.overloads[name](a, b); | |
} | |
return work(a, b); | |
}; | |
} | |
function make_overloads(o, r = {}) { | |
for (let i in o) { | |
r[o[i]] = factory(o[i], i); | |
} | |
return r; | |
} | |
let _modules = { | |
loaded: {}, | |
unloaded: {}, | |
_tryLoadUnloaded(name) { | |
const module = _modules.unloaded[name]; | |
if (module) { | |
let exports = new Proxy({}, { | |
get(target, p, r) { | |
return target[p]; | |
}, | |
set(target, p, v) { | |
Object.defineProperty(target, p, { | |
value: v | |
}); | |
return v; | |
} | |
}); | |
let passin = [_modules.require, exports]; | |
for (let i = 0; i < module.required.length; i++) { | |
if (module.required[i] == "require" || module.required[i] == "exports") { | |
continue; | |
} | |
_modules._tryLoadUnloaded(module.required[i]); | |
passin.push(_modules.loaded[module.required[i]]); | |
} | |
_modules.loaded[name] = module.definition(...passin) || exports; | |
delete _modules.unloaded[name]; | |
} | |
}, | |
require(thing) { | |
if (_modules.loaded[thing]) return _modules.loaded[thing]; | |
if (_modules.unloaded[thing]) return _modules.unloaded[thing]; | |
}, | |
overloads: make_overloads( /*%overloads%*/ ) | |
}; | |
function define(name, required, definition) { | |
let module = { | |
required, | |
definition | |
}; | |
_modules.unloaded[name] = module; | |
_modules._tryLoadUnloaded(name); | |
} | |
/*%content%*/ | |
})() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function () { | |
function factory(name, op) { | |
let work = new Function("a", "b", "return a" + op + "b"); | |
return (a, b) => { | |
let cons = a.constructor; | |
if (cons.overloads && cons.overloads[name]) { | |
return cons.overloads[name](a, b); | |
} | |
return work(a, b); | |
}; | |
} | |
function make_overloads(o, r = {}) { | |
for (let i in o) { | |
r[o[i]] = factory(o[i], i); | |
} | |
return r; | |
} | |
let _modules = { | |
loaded: {}, | |
unloaded: {}, | |
_tryLoadUnloaded(name) { | |
const module = _modules.unloaded[name]; | |
if (module) { | |
let exports = new Proxy({}, { | |
get(target, p, r) { | |
return target[p]; | |
}, | |
set(target, p, v) { | |
Object.defineProperty(target, p, { | |
value: v | |
}); | |
return v; | |
} | |
}); | |
let passin = [_modules.require, exports]; | |
for (let i = 0; i < module.required.length; i++) { | |
if (module.required[i] == "require" || module.required[i] == "exports") { | |
continue; | |
} | |
_modules._tryLoadUnloaded(module.required[i]); | |
passin.push(_modules.loaded[module.required[i]]); | |
} | |
_modules.loaded[name] = module.definition(...passin) || exports; | |
delete _modules.unloaded[name]; | |
} | |
}, | |
require(thing) { | |
if (_modules.loaded[thing]) return _modules.loaded[thing]; | |
if (_modules.unloaded[thing]) return _modules.unloaded[thing]; | |
}, | |
overloads: make_overloads( {"+":"PLUS","-":"MINUS","*":"MULTIPLY","/":"DIVIDE","%":"MOD","**":"EXPONENTIATION","^":"XOR","&":"AND","==":"EQUAL","!=":"NOTEQUAL","===":"STRICTEQUAL","!==":"STRICTNOTEQUAL","<":"LESSTHAN",">":"GREATERTHAN","<=":"LESSTHANEQUAL",">=":"GREATERTHANEQUAL","<<":"LEFTSHIFT",">>":"RIGHTSHIFT",">>>":"UNSIGNEDRIGHTSHIFT","|":"OR"} ) | |
}; | |
function define(name, required, definition) { | |
let module = { | |
required, | |
definition | |
}; | |
_modules.unloaded[name] = module; | |
_modules._tryLoadUnloaded(name); | |
} | |
define('types/Point', [ | |
'require', | |
'exports' | |
], function (require, exports) { | |
'use strict'; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
class Point { | |
constructor(x, y) { | |
this.x = x; | |
this.y = y; | |
} | |
add(o) { | |
return _modules.overloads.PLUS(this, o); | |
} | |
sub(o) { | |
return _modules.overloads.MINUS(this, o); | |
} | |
mult(o) { | |
return _modules.overloads.MULTIPLY(this, o); | |
} | |
div(o) { | |
return _modules.overloads.DIVIDE(this, o); | |
} | |
} | |
Point.overloads = { | |
PLUS(a, b) { | |
return new Point(_modules.overloads.PLUS(a.x, b.x), _modules.overloads.PLUS(a.y, b.y)); | |
}, | |
MINUS(a, b) { | |
return new Point(_modules.overloads.MINUS(a.x, b.x), _modules.overloads.MINUS(a.y, b.y)); | |
}, | |
MULTIPLY(a, b) { | |
return new Point(_modules.overloads.MULTIPLY(a.x, b.x), _modules.overloads.MULTIPLY(a.y, b.y)); | |
}, | |
DIVIDE(a, b) { | |
return new Point(_modules.overloads.DIVIDE(a.x, b.x), _modules.overloads.DIVIDE(a.y, b.y)); | |
}, | |
MOD(a, b) { | |
return new Point(_modules.overloads.MOD(a.x, b.x), _modules.overloads.MOD(a.y, b.y)); | |
}, | |
EXPONENTIATION(a, b) { | |
return new Point(_modules.overloads.EXPONENTIATION(a.x, b.x), _modules.overloads.EXPONENTIATION(a.y, b.y)); | |
}, | |
XOR(a, b) { | |
return new Point(_modules.overloads.XOR(a.x, b.x), _modules.overloads.XOR(a.y, b.y)); | |
}, | |
AND(a, b) { | |
return new Point(_modules.overloads.AND(a.x, b.x), _modules.overloads.AND(a.y, b.y)); | |
}, | |
LEFTSHIFT(a, b) { | |
return new Point(_modules.overloads.LEFTSHIFT(a.x, b.x), _modules.overloads.LEFTSHIFT(a.y, b.y)); | |
}, | |
RIGHTSHIFT(a, b) { | |
return new Point(_modules.overloads.RIGHTSHIFT(a.x, b.x), _modules.overloads.RIGHTSHIFT(a.y, b.y)); | |
}, | |
UNSIGNEDRIGHTSHIFT(a, b) { | |
return new Point(_modules.overloads.UNSIGNEDRIGHTSHIFT(a.x, b.x), _modules.overloads.UNSIGNEDRIGHTSHIFT(a.y, b.y)); | |
}, | |
OR(a, b) { | |
return new Point(_modules.overloads.OR(a.x, b.x), _modules.overloads.OR(a.y, b.y)); | |
} | |
}; | |
exports.default = Point; | |
}); | |
define('index', [ | |
'require', | |
'exports', | |
'types/Point' | |
], function (require, exports, Point_1) { | |
'use strict'; | |
Object.defineProperty(exports, '__esModule', { value: true }); | |
window['engine'] = { Point: Point_1.default }; | |
let a = new Point_1.default(1, 2); | |
let b = new Point_1.default(3, 4); | |
console.log(_modules.overloads.PLUS(a, b)); | |
}); | |
})() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Point from "./types/Point"; | |
window["engine"] = { | |
Point | |
} | |
//example operation | |
let a = new Point(1,2); | |
let b = new Point(3,4); | |
console.log(a+b); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Point { | |
x: number; | |
y: number; | |
constructor(x: number, y: number) { | |
this.x = x; | |
this.y = y; | |
} | |
// @enumerable(false) | |
static overloads = { | |
PLUS(a, b) { return new Point(a.x + b.x, a.y + b.y); }, | |
MINUS(a, b) { return new Point(a.x - b.x, a.y - b.y); }, | |
MULTIPLY(a, b) { return new Point(a.x * b.x, a.y * b.y); }, | |
DIVIDE(a, b) { return new Point(a.x / b.x, a.y / b.y); }, | |
MOD(a, b) { return new Point(a.x % b.x, a.y % b.y); }, | |
EXPONENTIATION(a, b) { return new Point(a.x ** b.x, a.y ** b.y); }, | |
XOR(a, b) { return new Point(a.x ^ b.x, a.y ^ b.y); }, | |
AND(a, b) { return new Point(a.x & b.x, a.y & b.y); }, | |
LEFTSHIFT(a, b) { return new Point(a.x << b.x, a.y << b.y); }, | |
RIGHTSHIFT(a, b) { return new Point(a.x >> b.x, a.y >> b.y); }, | |
UNSIGNEDRIGHTSHIFT(a, b) { return new Point(a.x >>> b.x, a.y >>> b.y); }, | |
OR(a, b) { return new Point(a.x | b.x, a.y | b.y); } | |
} | |
add(o) { | |
return (this as any) + o; | |
} | |
sub(o) { | |
return (this as any) - o; | |
} | |
mult(o) { | |
return (this as any) * o; | |
} | |
div(o) { | |
return (this as any) / o; | |
} | |
} | |
export default Point; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment