Skip to content

Commit c86cc65

Browse files
author
Mauricio Poppe
committed
initial commit
0 parents  commit c86cc65

23 files changed

+774
-0
lines changed

.editorconfig

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
end_of_line = lf
11+
12+
[*.md]
13+
trim_trailing_whitespace = false
14+
15+
[Makefile]
16+
indent_style = tab
17+
indent_size = 2

.eslintrc

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// ESLint Configuration for generator-node-npm
3+
//
4+
// author: @iMauricio
5+
// date: 3/18/2015
6+
//
7+
// Helpful resources:
8+
//
9+
// - rules: http://eslint.org/docs/rules/
10+
// - configuration: http://eslint.org/docs/configuring/
11+
//
12+
// temporarily disable warnings
13+
// /*eslint-disable */
14+
// ...
15+
// /*eslint-enable */
16+
{
17+
// check http://eslint.org/docs/configuring/#specifying-language-options
18+
"ecmaFeatures": {
19+
"generators": false
20+
},
21+
"parser": "espree",
22+
"env": {
23+
"node": true,
24+
"mocha": true,
25+
"browser": false // true in the case it's module which will be bundled
26+
},
27+
28+
// if the module needs globals set them here
29+
"globals": {},
30+
31+
// 0 - turn the rule off
32+
// 1 - turn the rule on as a warning (doesn't affect exit code)
33+
// 2 - turn the rule on as an error (exit code is 1 when triggered)
34+
"rules": {
35+
"yoda": 0, // allow non-literals to be first in comparison expressions
36+
"no-console": 0, // disallow use of console (off by default in the node environment)
37+
"no-trailing-spaces": 0, // disable throwing errors for trailing spaces
38+
"no-unused-expressions": 0, // disallow usage of expressions in statement position
39+
"quotes": [2, "single"], // specify whether double or single quotes should be used
40+
"strict": [2, "global"], // controls location of Use Strict Directives
41+
"no-unused-vars": [1, {
42+
"vars": "all",
43+
"args": "after-used"
44+
}],
45+
"no-shadow": 0, // disallow declaration of variables already declared in the outer scope
46+
"eol-last": 0, // enforce newline at the end of file, with no multiple empty lines
47+
"indent": [2, 2], // this option sets a specific tab width for your code
48+
"space-before-function-parentheses": [
49+
2, {
50+
"anonymous": "always",
51+
"named": "never"
52+
}
53+
]
54+
}
55+
}

.gitignore

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Created by https://www.gitignore.io
2+
3+
### Node ###
4+
# Dependency directory
5+
node_modules
6+
npm-debug.log
7+
8+
# Coverage directory used by tools like istanbul
9+
coverage
10+
11+
12+
### WebStorm ###
13+
## Directory-based project format:
14+
.idea/
15+
16+
## File-based project format:
17+
*.iml
18+
*.ipr
19+
*.iws
20+
21+
22+
### SublimeText ###
23+
# cache files for sublime text
24+
*.tmlanguage.cache
25+
*.tmPreferences.cache
26+
*.stTheme.cache
27+
28+
# workspace files are user-specific
29+
*.sublime-workspace
30+
31+
# project files should be checked into the repository, unless a significant
32+
# proportion of contributors will probably not be using SublimeText
33+
# *.sublime-project
34+
35+
# sftp configuration file
36+
sftp-config.json
37+
38+
39+
### Vim ###
40+
[._]*.s[a-w][a-z]
41+
[._]s[a-w][a-z]
42+
*.un~
43+
Session.vim
44+
.netrwhist
45+
*~

.travis.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
language: node_js
2+
env: CI=true
3+
sudo: false
4+
5+
node_js:
6+
- '0.10'
7+
8+
install:
9+
- npm install
10+
11+
script:
12+
- npm run lint
13+
- npm run istanbul && cat ./coverage/lcov.info | coveralls

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# math-codegen
2+
3+
[![NPM][npm-image]][npm-url]
4+
5+
[![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Dependency Status][david-image]][david-url]
6+
7+
> Generates code from mathematical expressions
8+
9+
## Install
10+
11+
```sh
12+
$ npm install --save math-codegen
13+
```
14+
15+
## Usage
16+
17+
```js
18+
var mathCodegen = require('math-codegen');
19+
mathCodegen('Rainbow');
20+
```
21+
22+
23+
## API
24+
25+
Coming soon...
26+
27+
## License
28+
29+
2015 MIT © [Mauricio Poppe]()
30+
31+
[npm-image]: https://nodei.co/npm/math-codegen.png?downloads=true
32+
[npm-url]: https://npmjs.org/package/math-codegen
33+
[travis-image]: https://travis-ci.org/maurizzzio/math-codegen.svg?branch=master
34+
[travis-url]: https://travis-ci.org/maurizzzio/math-codegen
35+
[coveralls-image]: https://coveralls.io/repos/maurizzzio/math-codegen/badge.svg
36+
[coveralls-url]: https://coveralls.io/r/maurizzzio/math-codegen
37+
[david-image]: https://david-dm.org/maurizzzio/math-codegen.svg
38+
[david-url]: https://david-dm.org/maurizzzio/math-codegen

index.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* math-codegen
3+
*
4+
* Copyright (c) 2015 Mauricio Poppe
5+
* Licensed under the MIT license.
6+
*/
7+
'use strict';
8+
module.exports = require('./lib/CodeGenerator');

lib/CodeGenerator.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/**
2+
* Created by mauricio on 5/12/15.
3+
*/
4+
'use strict';
5+
6+
var esprima = require('esprima');
7+
var Interpreter = require('./Interpreter');
8+
var extend = require('extend');
9+
10+
function CodeGenerator(options, defs) {
11+
this.statements = [];
12+
this.options = extend({
13+
factory: 'ns.factory',
14+
raw: false,
15+
rawArrayExpressionElements: true,
16+
rawCallExpressionElements: false
17+
}, options);
18+
this.defs = defs || {};
19+
this.interpreter = new Interpreter(this);
20+
}
21+
22+
CodeGenerator.prototype.setDefs = function (defs) {
23+
this.defs = extend(this.defs, defs);
24+
return this;
25+
};
26+
27+
CodeGenerator.prototype.compile = function () {
28+
if (typeof this.defs.ns !== 'object') {
29+
throw Error('"ns" property needs to be defined on defs');
30+
}
31+
32+
// default process scope hook
33+
this.defs._processScope = this.defs._processScope || function () {};
34+
35+
var defsCode = Object.keys(this.defs).map(function (name) {
36+
return 'var ' + name + ' = defs["' + name + '"];';
37+
});
38+
39+
// statement join
40+
if (!this.statements.length) {
41+
throw Error('there are no statements saved in this generator');
42+
}
43+
44+
// last statement is always a return statement
45+
this.statements[this.statements.length - 1] = 'return ' + this.statements[this.statements.length - 1];
46+
47+
var code = this.statements.join(';\n');
48+
var factoryCode =
49+
defsCode.join(' ') +
50+
'return {' +
51+
' eval: function (scope) {' +
52+
' scope = scope || {};' +
53+
' _processScope(scope);' +
54+
' ' + code +
55+
' },' +
56+
' code: \'' + code + '\'' +
57+
'};';
58+
59+
/* eslint-disable */
60+
var factory = new Function('defs', factoryCode);
61+
/* eslint-enable */
62+
return factory(this.defs);
63+
};
64+
65+
CodeGenerator.prototype.parse = function (code) {
66+
var self = this;
67+
var program = esprima.parse(code);
68+
this.statements = program.body.map(function (statement) {
69+
return self.interpreter.next(statement);
70+
});
71+
return this;
72+
};
73+
74+
module.exports = CodeGenerator;

lib/interpreter.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use strict';
2+
var extend = require('extend');
3+
var utils = require('./utils');
4+
5+
var types = {
6+
// node
7+
ArrayExpression: require('./node/ArrayExpression'),
8+
AssignmentExpression: require('./node/AssignmentExpression'),
9+
BinaryExpression: require('./node/BinaryExpression'),
10+
CallExpression: require('./node/CallExpression'),
11+
ConditionalExpression: require('./node/ConditionalExpression'),
12+
ExpressionStatement: require('./node/ExpressionStatement'),
13+
UnaryExpression: require('./node/UnaryExpression'),
14+
// misc
15+
Identifier: require('./misc/Identifier'),
16+
Literal: require('./misc/Literal')
17+
};
18+
19+
var Interpreter = function (owner) {
20+
this.options = owner.options;
21+
};
22+
23+
extend(Interpreter.prototype, types);
24+
25+
// run is the main method which decides which expression to call
26+
Interpreter.prototype.next = function (node) {
27+
if (!(node.type in this)) {
28+
throw new TypeError('the node type ' + node.type + ' is not implemented');
29+
}
30+
return this[node.type](node);
31+
};
32+
33+
Interpreter.prototype.rawify = utils.rawify;
34+
35+
module.exports = Interpreter;

lib/misc/BinaryOperator.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
// https://github.com/estree/estree/blob/master/spec.md#binaryoperator
4+
module.exports = {
5+
'+': 'add',
6+
'-': 'sub',
7+
'*': 'mul',
8+
'/': 'div',
9+
'^': 'pow',
10+
'%': 'mod',
11+
'<': 'lessThan',
12+
'>': 'greaterThan',
13+
'<=': 'lessEqualThan',
14+
'>=': 'greaterEqualThan'
15+
};

lib/misc/Identifier.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
module.exports = function (node) {
3+
var id = node.name;
4+
return '(scope["' + id + '"] || ' +
5+
'ns["' + id + '"] || ' + id + ' )';
6+
};

lib/misc/Literal.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict';
2+
module.exports = function (node) {
3+
// TODO: check the type of node.value/node.raw
4+
if (this.options.raw) {
5+
return node.raw;
6+
}
7+
return this.options.factory + '(' + node.raw + ')';
8+
};

lib/misc/UnaryOperator.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
'use strict';
2+
3+
// https://github.com/estree/estree/blob/master/spec.md#unaryoperator
4+
module.exports = {
5+
'+': 'positive',
6+
'-': 'negative',
7+
'!': 'logicalNegation',
8+
'~': 'oneComplement'
9+
};

lib/node/ArrayExpression.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use strict';
2+
module.exports = function (node) {
3+
var self = this;
4+
var arr = [];
5+
this.rawify(this.options.rawArrayExpressionElements, function () {
6+
arr = node.elements.map(function (el) {
7+
return self.next(el);
8+
});
9+
});
10+
var arrString = '[' + arr.join(',') + ']';
11+
12+
if (this.options.raw) {
13+
return arrString;
14+
}
15+
return this.options.factory + '(' + arrString + ')';
16+
};

lib/node/AssignmentExpression.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Created by mauricio on 5/14/15.
3+
*/
4+
'use strict';
5+
6+
// https://github.com/estree/estree/blob/master/spec.md#binaryoperator
7+
var operators = {
8+
'=': equalOperator
9+
};
10+
11+
function equalOperator(node) {
12+
return '(scope["' + node.left.name + '"] = ' + this.next(node.right) + ')';
13+
}
14+
15+
module.exports = function (node) {
16+
if (!(node.operator in operators)) {
17+
throw SyntaxError(node.operator + ' not implemented');
18+
}
19+
return operators[node.operator].call(this, node);
20+
};

lib/node/BinaryExpression.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
3+
var operators = require('../misc/BinaryOperator');
4+
5+
module.exports = function (node) {
6+
if (this.options.raw) {
7+
return ['(' + this.next(node.left), node.operator, this.next(node.right) + ')'].join(' ');
8+
}
9+
10+
if (!(node.operator in operators)) {
11+
throw SyntaxError(node.operator + ' not implemented');
12+
}
13+
14+
// transform to CallExpression
15+
var binaryNode = {
16+
callee: {
17+
type: 'Identifier',
18+
name: operators[node.operator]
19+
},
20+
arguments: [node.left, node.right]
21+
};
22+
23+
return this.CallExpression(binaryNode);
24+
};

0 commit comments

Comments
 (0)