https://github.com/featurist/dslify
JavaScript function rewriter, for little DSLs
https://github.com/featurist/dslify
Last synced: 3 months ago
JSON representation
JavaScript function rewriter, for little DSLs
- Host: GitHub
- URL: https://github.com/featurist/dslify
- Owner: featurist
- License: bsd-2-clause
- Created: 2013-06-29T12:57:52.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2018-02-09T14:31:13.000Z (almost 8 years ago)
- Last Synced: 2025-09-27T08:58:54.460Z (4 months ago)
- Language: PogoScript
- Size: 41 KB
- Stars: 12
- Watchers: 5
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# dslify
Rewrites a JavaScript function or module, such that any global property access
is transformed to call a member of a new _dsl_ argument. Use dslify to interpret
domain-specific languages without messing around in global scope.
[](http://travis-ci.org/featurist/dslify)
[](https://david-dm.org/featurist/dslify)
### Install
npm install dslify
### Rewriting Functions
```js
var dslify = require('dslify')
var script = function() {
return addHorn(addLegs(makeAnimal()))
}
var factory = dslify.transform(script)
var dsl = {
makeAnimal() {
return {}
},
addLegs(animal) {
animal.legs = 4
return animal
},
addHorn(animal) {
animal.horns = 1
return animal
}
}
factory(dsl) // => { legs: 4, horns: 1 }
```
Sometimes you might want to operate with strings instead of JavaScript functions. For
example if you are generating templates or want to send JavaScript to the client.
```js
var dslify = require('dslify')
var input = "function(input) { return shout(input, globalValue) }"
var output = dslify.transform(input, { asString: true })
output // => function(input) { return shout(input, _dsl.globalValue) }
```
### Rewriting Modules
By rewriting an entire module in terms of another 'dsl' interpreter module, you
can make slightly larger DSLs:
```js
// abstract.js
module.exports = {
log: function(message) {
print(message);
}
};
// printer.js
module.exports = {
print: function(message) {
console.log(message + '!')
}
};
// compile.js
var dslify = require('dslify');
var abstract = require('fs').readFileSync('./abstract.js', 'utf-8');
var concrete = dslify.transformModule(abstract, './printer');
fs.writeFileSync('./concrete.js', concrete);
// then...
var concrete = require('./concrete.js');
concrete.log('jibber jabber'); // -> jibber jabber!
```
### How?
dslify parses JavaScript using [esprima](https://github.com/ariya/esprima), rewriting it as new JavaScript using [escodegen](https://github.com/Constellation/escodegen).
### Hold on, isn't this just a long-winded JavaScript 'with'?
Yes. But 'with' is [leaky and dangerous](http://www.yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/), wheras dslify is like a sandbox because it rewrites access to global scope, e.g:
```js
var dslify = require('dslify');
var dsl = {};
var withWith = function(dsl) {
with (dsl) {
y = 'leaks into global!';
}
};
var withDslify = dslify.transform(function() {
z = 'global is safe!';
});
withWith(dsl);
withDslify(dsl);
console.log(global.y); // leaks into global!
console.log(global.z); // undefined
console.log(dsl.z); // global is safe!
```
### Isn't it hard to debug dynamically-generated functions?
Yes. And dynamically generating functions is relatively slow, compared to calling
functions. Therefore consider transforming functions at build time instead of run time.
### License
BSD
## We're Hiring!
Featurist provides full stack, feature driven development teams. Want to join us? Check out [our career opportunities](https://www.featurist.co.uk/careers/).