Comparing version 0.3.1 to 1.0.0
110
index.js
@@ -5,3 +5,2 @@ "use strict"; | ||
//- LabeledStatement -> including use in break/continue | ||
//- ForInStatement -> there is a start, finish it. | ||
//- nicer error handling? | ||
@@ -50,2 +49,4 @@ //-> TESTS | ||
this._boundGen = this._gen.bind(this); | ||
this.DEBUG = false; | ||
} | ||
@@ -62,2 +63,9 @@ | ||
Environment.prototype.gen = function (node) { | ||
var opts = {}; | ||
if (this.DEBUG) { | ||
opts.locations = true; | ||
} | ||
if (typeof node === 'string') { | ||
node = parse(node, opts); | ||
} | ||
var resp = this._gen(node); | ||
@@ -70,3 +78,3 @@ addDeclarationsToStore(this._curDeclarations, this._curVarStore); | ||
Environment.prototype._gen = function (node) { | ||
return ({ | ||
var closure = ({ | ||
BinaryExpression: this._genBinExpr, | ||
@@ -110,36 +118,52 @@ LogicalExpression: this._genBinExpr, | ||
}).call(this, node); | ||
if (this.DEBUG) { | ||
return function () { | ||
var info = 'closure for ' + node.type + ' called'; | ||
var line = ((node.loc || {}).start || {}).line; | ||
if (line) { | ||
info += ' while processing line ' + line; | ||
} | ||
var resp = closure(); | ||
info += '. Result:'; | ||
console.log(info, resp); | ||
return resp; | ||
}; | ||
} | ||
return closure; | ||
}; | ||
Environment.prototype._genBinExpr = function (node) { | ||
var a = this._gen(node.left); | ||
var b = this._gen(node.right); | ||
var cmp = { | ||
'==': function (a, b) {return a == b; }, | ||
'!=': function (a, b) {return a != b; }, | ||
'===': function (a, b) {return a === b; }, | ||
'!==': function (a, b) {return a !== b; }, | ||
'<': function (a, b) {return a < b; }, | ||
'<=': function (a, b) {return a <= b; }, | ||
'>': function (a, b) {return a > b; }, | ||
'>=': function (a, b) {return a >= b; }, | ||
'<<': function (a, b) {return a << b; }, | ||
'>>': function (a, b) {return a >> b; }, | ||
'>>>': function (a, b) {return a >>> b; }, | ||
'+': function (a, b) {return a + b; }, | ||
'-': function (a, b) {return a - b; }, | ||
'*': function (a, b) {return a * b; }, | ||
'/': function (a, b) {return a / b; }, | ||
'%': function (a, b) {return a % b; }, | ||
'|': function (a, b) {return a | b; }, | ||
'^': function (a, b) {return a ^ b; }, | ||
'&': function (a, b) {return a & b; }, | ||
'in': function (a, b) {return a in b; }, | ||
'instanceof': function (a, b) {return a instanceof b; }, | ||
'==': function () {return a() == b(); }, | ||
'!=': function () {return a() != b(); }, | ||
'===': function () {return a() === b(); }, | ||
'!==': function () {return a() !== b(); }, | ||
'<': function () {return a() < b(); }, | ||
'<=': function () {return a() <= b(); }, | ||
'>': function () {return a() > b(); }, | ||
'>=': function () {return a() >= b(); }, | ||
'<<': function () {return a() << b(); }, | ||
'>>': function () {return a() >> b(); }, | ||
'>>>': function () {return a() >>> b(); }, | ||
'+': function () {return a() + b(); }, | ||
'-': function () {return a() - b(); }, | ||
'*': function () {return a() * b(); }, | ||
'/': function () {return a() / b(); }, | ||
'%': function () {return a() % b(); }, | ||
'|': function () {return a() | b(); }, | ||
'^': function () {return a() ^ b(); }, | ||
'&': function () {return a() & b(); }, | ||
'in': function () {return a() in b(); }, | ||
'instanceof': function () {return a() instanceof b(); }, | ||
// logic expressions | ||
'||': function (a, b) {return a || b; }, | ||
'&&': function (a, b) {return a && b; }, | ||
'||': function () {return a() || b(); }, | ||
'&&': function () {return a() && b(); }, | ||
}[node.operator]; | ||
var left = this._gen(node.left); | ||
var right = this._gen(node.right); | ||
return function () { | ||
return cmp(left(), right()); | ||
return cmp(); | ||
}; | ||
@@ -466,3 +490,3 @@ }; | ||
Environment.prototype._genRetStmt = function (node) { | ||
var arg = this._gen(node.argument); | ||
var arg = node.argument ? this._gen(node.argument) : noop; | ||
return function () { | ||
@@ -521,4 +545,3 @@ return new Return(arg()); | ||
Environment.prototype._genForInStmt = function (node) { | ||
/* var self = this; | ||
var left = self._gen(node.left); | ||
var self = this; | ||
var right = self._gen(node.right); | ||
@@ -529,2 +552,3 @@ var body = self._gen(node.body); | ||
if (left.type === 'VariableDeclaration') { | ||
self._curDeclarations.push(left.declarations[0].id.name); | ||
left = left.declarations[0].id; | ||
@@ -534,4 +558,5 @@ } | ||
var resp; | ||
for (x in right()) { | ||
for (var x in right()) { | ||
self._genAssignExpr({ | ||
operator: '=', | ||
left: left, | ||
@@ -546,4 +571,3 @@ right: { | ||
return resp; | ||
};*/ | ||
return noop; | ||
}; | ||
}; | ||
@@ -573,14 +597,11 @@ | ||
var handler = this._genCatchHandler(node.handler); | ||
var finalizer = node.finalizer ? this._gen(node.finalizer) : null; | ||
var finalizer = node.finalizer ? this._gen(node.finalizer) : function (x) { | ||
return x; | ||
}; | ||
return function () { | ||
try { | ||
block(); | ||
return finalizer(block()); | ||
} catch (err) { | ||
var resp = handler(err); | ||
if (!finalizer) { | ||
return resp; | ||
} | ||
} finally { | ||
return finalizer(); | ||
return finalizer(handler(err)); | ||
} | ||
@@ -660,5 +681,4 @@ }; | ||
exports.evaluate = function (code) { | ||
var ast = parse(code); | ||
var env = new Environment(global); | ||
var resp = env.gen(ast)(); | ||
var resp = env.gen(code)(); | ||
return resp; | ||
@@ -665,0 +685,0 @@ }; |
{ | ||
"name": "evaljs", | ||
"version": "0.3.1", | ||
"version": "1.0.0", | ||
"description": "A JavaScript interpreter written in JavaScript", | ||
"main": "index.js", | ||
"bin": "./bin/evaljs", | ||
"dependencies": { | ||
@@ -11,2 +12,3 @@ "acorn": "^0.11.0" | ||
"browserify": "^8.1.1", | ||
"esprima": "^1.2.3", | ||
"is-optimizable": "^1.1.0", | ||
@@ -13,0 +15,0 @@ "jshint": "^2.5.11", |
@@ -31,2 +31,30 @@ eval.js | ||
Command line interface | ||
---------------------- | ||
This npm package comes with a REPL which allows you to experiment with | ||
it. It's easy to install and use: | ||
``` | ||
marten@procyon:~/git/evaljs$ npm install -g evaljs | ||
marten@procyon:~/git/evaljs$ evaljs | ||
> 1 + 1 | ||
2 | ||
> new Error('Hello World!') | ||
[Error: Hello World!] | ||
> throw new Error('Hello World!') | ||
Error: Hello World! | ||
at newWithArgs (/home/marten/git/evaljs/index.js:255:10) | ||
at /home/marten/git/evaljs/index.js:249:12 | ||
at Array.0 (/home/marten/git/evaljs/index.js:581:11) | ||
at /home/marten/git/evaljs/index.js:466:31 | ||
at REPLServer.repl.start.eval (/home/marten/git/evaljs/bin/evaljs:12:34) | ||
at repl.js:249:20 | ||
at REPLServer.repl.start.eval (/home/marten/git/evaljs/bin/evaljs:14:7) | ||
at Interface.<anonymous> (repl.js:239:12) | ||
at Interface.EventEmitter.emit (events.js:95:17) | ||
at Interface._onLine (readline.js:202:10) | ||
> marten@procyon:~/git/evaljs$ | ||
``` | ||
API | ||
@@ -48,2 +76,10 @@ --- | ||
A JS Environment has the following properties: | ||
- ``env.gen(node)``: Takes either the result of acorn's ``parse()`` | ||
method (an AST), or a JS string containing source code. This | ||
AST/code will be converted into a function that, when run, executes | ||
the AST/code passed in and returns the result. | ||
- ``env.DEBUG``: When set to ``true``, evaljs will write debug | ||
information to stdout. | ||
Size? | ||
@@ -62,5 +98,6 @@ ----- | ||
No labeled statements; no nice error handling; no for-in loops. There | ||
are probably bugs. That said, it can run itself so its supported subset | ||
of JS is usable. PRs containing improvements welcome! | ||
No labeled statements; no nice error handling (although there is a | ||
``DEBUG`` option). There are probably bugs. That said, it can run itself | ||
including acorn without modifications, so its supported subset of JS is | ||
usable. PRs containing improvements welcome! | ||
@@ -67,0 +104,0 @@ How slow is it? |
24
test.js
@@ -7,2 +7,6 @@ "use strict"; | ||
// basic | ||
console.log(evaljs.evaluate('1 + 1')); | ||
// theTest.js | ||
var code = fs.readFileSync('theTest.js', {encoding: 'UTF-8'}); | ||
@@ -13,3 +17,3 @@ | ||
//index.js | ||
// index.js | ||
var code = fs.readFileSync('index.js', {encoding: 'UTF-8'}); | ||
@@ -22,3 +26,19 @@ | ||
var env = new evaljs.Environment([envGlobal, modLocal]); | ||
env.gen(parse(code))(); | ||
env.gen(code)(); | ||
// acorn.js | ||
var code = fs.readFileSync(require.resolve('acorn/acorn_csp'), {encoding: 'UTF-8'}); | ||
var env = new evaljs.Environment([global, {exports: {}, module: {}}]); | ||
//env.DEBUG = true; | ||
// load library | ||
env.gen(code)(); | ||
// parse file | ||
var parsed = env.gen('exports.parse("1 + 1")')(); | ||
// for bonus points: run the parsed expression | ||
console.log(env.gen(parsed)()); | ||
// using esprima | ||
var esprima = require('esprima'); | ||
console.log(evaljs.evaluate(esprima.parse('1 + 1'))); |
@@ -162,7 +162,10 @@ // not strict, 'cause we need to parse the with statement | ||
/* | ||
var z; | ||
for (z in {a: 1, b: 2}) { | ||
console.log(z); | ||
} | ||
for (var key in {a: 1, b: 2}) { | ||
console.log(key); | ||
} | ||
*/ | ||
@@ -169,0 +172,0 @@ /*jshint ignore:start*/ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
184348
11
3736
2
114
5