soltar
Version:
Generate Solidity Code from solidity-parser's AST
1,868 lines (1,544 loc) • 42.8 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
*@fileoverview Implementation of code generating engine
*@author Raghav Dua
*/
'use strict';
var Syntax = require ('sol-explore').Syntax,
Soltar = {
version: require ('./package.json').version
};
/**
* Get the default options object - describes the default look of the generated code.
* @returns {Void}
*/
function getDefaultOptions () {
return {
format: {
indent: {
style: '\t',
base: 0
},
newline: '\n',
space: ' ',
quotes: 'single',
minify: false
}
};
}
/**
* Get the minify options object - describes the look of the generated code when minified.
* @returns {Void}
*/
function getMinifyOptions () {
return {
format: {
indent: {
style: '',
base: 0
},
newline: '',
space: ' ',
quotes: 'single',
minify: true
}
};
}
/**
* Determine whether the parameter passed is a non-null, non-array JS Object
* @param {*} i Any data type that the user wishes to check for Object Property
* @returns {Boolean}
*/
function isStrictlyObject (i) {
return (
i !== null && //because typeof null equals 'object', make sure the object is non-null
typeof i === 'object' &&
i.constructor !== Array
);
}
/**
* Determine whether the parameter passed is a Spider-Monkey compliant AST Node
* @param {*} possibleNode Any data type that the user wishes to check for AST Node property
* @returns {Boolean}
*/
function isASTNode (possibleNode) {
return (
isStrictlyObject (possibleNode) &&
possibleNode.type &&
typeof possibleNode.type === 'string'
);
}
/**
* Determine whether the AST Node passed represents a Statement (eg- ContractStatement, etc.)
* @param {ASTNode} node The AST Node to check the type of
* @returns {Boolean}
*/
function isStatement (node) {
return CodeGenerator.Statement.hasOwnProperty (node.type);
}
/**
* Determine whether the AST Node passed represents an Expression (eg- ArrayExpression, etc.)
* @param {ASTNode} node The AST Node to check the type of
* @returns {Boolean}
*/
function isExpression (node) {
return CodeGenerator.Expression.hasOwnProperty (node.type);
}
/**
* Determine whether the provided literal is in Hex Notation
* @param {String} literal The literal to test for Hex Notation
* @returns {Boolean}
*/
function isHex (literal) {
var reg = /^[0-9a-f]+$/i;
//test for '0x' separately because hex notation should not be a part of the standard RegExp
if (literal.slice (0, 2) !== '0x') {
return false;
}
return reg.test (literal.slice (2));
}
/**
* Merge all properties of source object into target object (by reference)
* @param {Object} target
* @param {Object} source
* @returns {Object} target The target object, returned for chainability
*/
function mergeObjects (target, source) {
Object.keys (source).forEach (function (key) {
target [key] = source [key];
});
return target;
}
/**
* Create a string of a pattern repeated N times
* @param {String} str The base string, i.e., the pattern
* @param {Integer} times The number of times str must be repeated
* @returns {String} string The string generated by repeating str N times
*/
function repeatString (str, times) {
return Array (times+1).join (str);
}
function append (mainString, subString) {
return mainString + subString;
}
function removeAppended (mainString, subString) {
return mainString.slice (0, -subString.length);
}
/**
* Merge all the units generated from individual AST Nodes into the final string (the source code)
* @param {Array|String} arrayOrString A String is returned as it is, the Array is recursively traversed to extract all strings to merge
* @returns {String} result The string generated by merging all components
*/
function flatten (arrayOrString) {
if (typeof arrayOrString === 'string') {
return arrayOrString;
} else if (typeof arrayOrString === 'object' &&
arrayOrString.constructor === Array) {
var result = '';
for (var i = 0; i < arrayOrString.length; i++) {
result += flatten (arrayOrString [i]);
}
return result;
}
throw new Error ('Invalid argument type');
}
/**
* Normalize opts with defaultOpts, i.e., create the properties in opts that don't exist in opts but do in defaultOpts and set their values to those of defaultOpts
* @param {Object} defaultOpts
* @param {Object} opts
* @returns {Object} options The final (normalized) options object
*/
function fillGapsDeeply (defaultOpts, opts) {
var options = {};
Object.keys (defaultOpts).forEach (function (key) {
var defOpt = defaultOpts [key];
if (isStrictlyObject (defOpt)) {
options [key] = fillGapsDeeply (defOpt, opts [key] || {})
} else {
options [key] = opts [key] || defOpt;
}
});
return options;
}
var CodeGenerator = function CodeGenerator () {
if (!(this instanceof CodeGenerator)) {
return new CodeGenerator ();
}
}
CodeGenerator.prototype.init = function (config) {
var format = config.format;
this._indent = repeatString (format.indent.style, format.indent.base);
this._indentStyle = format.indent.style;
this._space = format.space;
this._lineBreak = format.newline;
switch (format.quotes) {
case 'single':
this._quote = '\'';
break;
case 'double':
this._quote = '\"';
break;
default:
throw new Error ('Invalid value specified for quotes (use \'single\' or \'double\')');
}
return this; //because chainability = SWAG
};
CodeGenerator.prototype.generateStatement = function (node) {
return this [node.type] (node);
};
CodeGenerator.prototype.generateExpression = function (node) {
return this [node.type] (node);
};
CodeGenerator.prototype.generate = function (node) {
if (isStatement (node)) {
return this.generateStatement (node);
}
if (isExpression (node)) {
return this.generateExpression (node);
}
throw new Error ('Unknown node type: ' + node.type);
};
CodeGenerator.Statement = {
BlockStatement: function (node) {
var GENERATOR_OBJECT = this, result = [];
if (!node.body.length) {
return '{}';
}
result = [
'{',
GENERATOR_OBJECT._lineBreak
];
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.body.forEach (function (item) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item),
GENERATOR_OBJECT._lineBreak
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result.push (GENERATOR_OBJECT._indent, '}');
return result;
},
BreakStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.break
];
if (node.label) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.label.type] (node.label)
);
}
result.push (';');
return result;
},
CatchClause: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.catch,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.param.type] (node.param),
')',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
];
return result;
},
ContinueStatement: function (node) {
return (
Syntax.continue +
(node.label ?
(this._space + this [node.label.type] (node.label)) : ''
) +
';'
);
},
ContractStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.contract,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space
];
if (node.is.length) {
result.push (Syntax.is, GENERATOR_OBJECT._space);
node.is.forEach (function (parent) {
result.push (
GENERATOR_OBJECT [parent.type] (parent),
',',
GENERATOR_OBJECT._space
);
});
}
result.splice (-2, 1); //remove the last (extra) comma
result.push ('{');
if (node.body) {
result.push (GENERATOR_OBJECT._lineBreak);
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.body.forEach (function (item) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item),
GENERATOR_OBJECT._lineBreak,
GENERATOR_OBJECT._lineBreak
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result [result.length - 1] = GENERATOR_OBJECT._indent; //remove the last (extra) line break & add indent
}
result.push ('}');
return result;
},
DebuggerStatement: function (node) {
return 'debugger;';
},
DoWhileStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.do,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body),
GENERATOR_OBJECT._space,
Syntax.while,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.test.type] (node.test),
');'
];
return result;
},
EmptyStatement: function (node) {
return ';';
},
EnumDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.enum,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space,
'{',
GENERATOR_OBJECT._lineBreak
];
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.members.forEach (function (member) {
result.push (
GENERATOR_OBJECT._indent,
member,
',',
GENERATOR_OBJECT._lineBreak
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result [result.length - 2] = GENERATOR_OBJECT._lineBreak;
result [result.length - 1] = GENERATOR_OBJECT._indent;
result.push ('}');
return result;
},
EventDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.event,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space,
'('
];
if (node.params) {
node.params.forEach (function (param) {
result.push (
GENERATOR_OBJECT [param.type] (param),
',',
GENERATOR_OBJECT._space
);
});
result.splice (-2, 2);
}
result.push (')');
if (node.modifiers) {
node.modifiers.forEach (function (modifier) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [modifier.type] (modifier)
);
});
}
result.push (';');
return result;
},
ExpressionStatement: function (node) {
var GENERATOR_OBJECT = this, result = [];
result = [
GENERATOR_OBJECT [node.expression.type] (node.expression),
';'
];
return result;
},
ForInStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.for,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.left.type] (node.left),
GENERATOR_OBJECT._space,
Syntax.in,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.right.type] (node.right),
')',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
];
return result;
},
ForStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.for,
GENERATOR_OBJECT._space,
'('
];
if (node.init) {
result.push (GENERATOR_OBJECT [node.init.type] (node.init));
}
result.push (';');
if (node.test) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.test.type] (node.test)
);
}
result.push (';');
if (node.update) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.update.type] (node.update)
);
}
result.push (
')',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
);
return result;
},
FunctionDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.function,
GENERATOR_OBJECT._space
];
if (node.name) {
result.push (
node.name,
GENERATOR_OBJECT._space
);
}
result.push ('(');
if (node.params) {
node.params.forEach (function (param) {
result.push (
GENERATOR_OBJECT [param.type] (param),
',',
GENERATOR_OBJECT._space
);
});
result.splice (-2, 2);
}
result.push (')');
if (node.modifiers) {
result.push (GENERATOR_OBJECT._space);
node.modifiers.forEach (function (modifier) {
result.push (
GENERATOR_OBJECT [modifier.type] (modifier),
GENERATOR_OBJECT._space
);
});
result.splice (-1, 1);
}
if (node.is_abstract) {
result.push (';');
} else if (node.body) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
);
} else {
throw new Error ('Invalid format for FunctionDeclaration');
}
return result;
},
IfStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.if,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.test.type] (node.test),
')',
node.consequent.type !== 'EmptyStatement' ? GENERATOR_OBJECT._space : '',
GENERATOR_OBJECT [node.consequent.type] (node.consequent)
];
if (node.alternate) {
result.push (
GENERATOR_OBJECT._space,
Syntax.else,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.alternate.type] (node.alternate)
);
}
return result;
},
ImportStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.import,
GENERATOR_OBJECT._space
];
if (node.symbols.length) {
if (node.symbols.length === 1) {
result.push (
GENERATOR_OBJECT [node.symbols [0].type] (node.symbols [0])
);
} else {
result.push ('{', GENERATOR_OBJECT._space);
node.symbols.forEach (function (symbol) {
result.push (
GENERATOR_OBJECT [symbol.type] (symbol),
',',
GENERATOR_OBJECT._space
);
});
result [result.length - 2] = GENERATOR_OBJECT._space; //remove last comma & add space
result [result.length - 1] = '}';
}
result.push (
GENERATOR_OBJECT._space,
Syntax.from,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT._quote,
node.from,
GENERATOR_OBJECT._quote,
';'
);
} else if (node.alias) {
result.push (
GENERATOR_OBJECT._quote,
node.from,
GENERATOR_OBJECT._quote,
GENERATOR_OBJECT._space,
Syntax.as,
GENERATOR_OBJECT._space,
node.alias,
';'
);
} else {
result.push (
GENERATOR_OBJECT._quote,
node.from,
GENERATOR_OBJECT._quote,
';'
);
}
return result;
},
InformalParameter: function (node) {
var GENERATOR_OBJECT = this, result;
result = [GENERATOR_OBJECT [node.literal.type] (node.literal)];
if (node.is_indexed) {
result.push (
GENERATOR_OBJECT._space,
Syntax.indexed
);
}
if (node.is_storage) {
result.push (
GENERATOR_OBJECT._space,
Syntax.storage
);
}
if (node.id) {
result.push (
GENERATOR_OBJECT._space,
node.id
);
}
return result;
},
LabeledStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.label.type] (node.label),
':',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
];
return result;
},
LibraryStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.library,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space
];
if (node.is.length) {
result.push (Syntax.is, GENERATOR_OBJECT._space);
node.is.forEach (function (parent) {
result.push (
GENERATOR_OBJECT [parent.type] (parent),
',',
GENERATOR_OBJECT._space
);
});
}
result.splice (-2, 1); //remove the last (extra) comma
result.push ('{');
if (node.body) {
result.push (GENERATOR_OBJECT._lineBreak);
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.body.forEach (function (item) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item),
GENERATOR_OBJECT._lineBreak,
GENERATOR_OBJECT._lineBreak
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result [result.length - 1] = GENERATOR_OBJECT._indent; //remove the last (extra) line break & add indent
}
result.push ('}');
return result;
},
ModifierDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.modifier,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space
];
if (node.params === null) {
result.push ('()');
} else if (node.params.length) {
result.push ('(');
node.params.forEach (function (param) {
result.push (
GENERATOR_OBJECT [param.type] (param),
',',
GENERATOR_OBJECT._space
);
});
result [result.length - 2] = ')';
}
if (node.modifiers) {
node.modifiers.forEach (function (modifier) {
result.push (
GENERATOR_OBJECT [modifier.type] (modifier),
GENERATOR_OBJECT._space
);
});
}
result.push (GENERATOR_OBJECT [node.body.type] (node.body));
return result;
},
ModifierName: function (node) {
var GENERATOR_OBJECT = this, result = [node.name];
if (node.params.length) {
result.push (
GENERATOR_OBJECT._space,
'('
);
node.params.forEach (function (param) {
result.push (
GENERATOR_OBJECT [param.type] (param),
',',
GENERATOR_OBJECT._space
);
});
result.splice (-2, 1);
result [result.length - 1] = ')';
}
return result;
},
Program: function (node) {
var GENERATOR_OBJECT = this, result = [];
if (!node.body.length) {
return '';
}
node.body.forEach (function (item) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item),
GENERATOR_OBJECT._lineBreak,
GENERATOR_OBJECT._lineBreak
);
});
result = result.slice (0, -2); //remove last 2 empty lines
return result;
},
ReturnStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.return
];
if (node.argument) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.argument.type] (node.argument)
);
}
result.push (';');
return result;
},
StructDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.struct,
GENERATOR_OBJECT._space,
node.name,
GENERATOR_OBJECT._space,
'{'
];
if (node.body.length) {
result.push (GENERATOR_OBJECT._lineBreak);
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.body.forEach (function (item) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item),
';',
GENERATOR_OBJECT._lineBreak
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
}
result.push (GENERATOR_OBJECT._indent, '}');
return result;
},
SwitchCase: function (node) {
var GENERATOR_OBJECT = this, result;
if (node.test) {
result = [
Syntax.case,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.test.type] (node.test)
];
} else {
result = [Syntax.default];
}
result.push (':');
if (node.consequent.length) {
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.consequent.forEach (function (item) {
result.push (
GENERATOR_OBJECT._lineBreak,
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [item.type] (item)
);
});
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
}
return result;
},
SwitchStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.switch,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.discriminant.type] (node.discriminant),
')',
GENERATOR_OBJECT._space,
'{'
];
if (node.cases.length) {
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.cases.forEach (function (caseHandler) {
result.push (
GENERATOR_OBJECT._lineBreak,
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [caseHandler.type] (caseHandler)
);
});
result.push (GENERATOR_OBJECT._lineBreak);
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
}
result.push (GENERATOR_OBJECT._indent, '}');
return result;
},
Symbol: function (node) {
if (node.name === node.alias) {
return node.name;
}
return (
node.name + this._space + Syntax.as + this._space + node.alias
);
},
ThrowStatement: function (node) {
return Syntax.throw + ';';
},
TryStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.try,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.block.type] (node.block)
];
if (node.handler) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.handler.type] (node.handler)
);
}
if (node.finalizer) {
result.push (
GENERATOR_OBJECT._space,
Syntax.finally,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.finalizer.type] (node.finalizer)
);
}
return result;
},
UnaryExpression: function (node) {
var GENERATOR_OBJECT = this, result;
var possibleSpace = (
(node.operator === Syntax.void ||
node.operator === Syntax.delete ||
node.operator === Syntax.typeof) ?
GENERATOR_OBJECT._space : ''
);
result = [
node.operator,
possibleSpace, //provide space if operator is 'delete', 'void' or 'typeof'
GENERATOR_OBJECT [node.argument.type] (node.argument)
];
return result;
},
UsingStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.using + this._space + node.library + this._space + Syntax.for + this._space,
typeof node.for === 'string' ? node.for : this [node.for.type] (node.for),
';'
];
return result;
},
VariableDeclaration: function (node) {
var GENERATOR_OBJECT = this, result;
result = [Syntax.var];
node.declarations.forEach (function (declaration) {
result.push (
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [declaration.type] (declaration),
','
);
});
result [result.length - 1] = ';'; //replace trailing comman with semicolon
return result;
},
VariableDeclarationTuple: function (node) {
var GENERATOR_OBJECT = this, result;
result = [Syntax.var, GENERATOR_OBJECT._space, '('];
node.declarations.forEach (function (declaration) {
result.push (
GENERATOR_OBJECT [declaration.type] (declaration),
',',
GENERATOR_OBJECT._space
);
});
result [result.length - 2] = ')';
result.push ('=', GENERATOR_OBJECT._space, GENERATOR_OBJECT [node.init.type] (node.init), ';');
return result;
},
VariableDeclarator: function (node) {
var GENERATOR_OBJECT = this, result;
result = [GENERATOR_OBJECT [node.id.type] (node.id)];
if (node.init) {
result.push (
GENERATOR_OBJECT._space,
'=',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.init.type] (node.init)
);
}
return result;
},
WhileStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.while,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.test.type] (node.test),
')',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
];
return result;
},
WithStatement: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.with,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.object.type] (node.object),
')',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.body.type] (node.body)
];
return result;
}
};
mergeObjects (CodeGenerator.prototype, CodeGenerator.Statement);
CodeGenerator.Expression = {
ArrayExpression: function (node) {
var GENERATOR_OBJECT = this, result;
if (!node.elements.length) {
return '[]';
}
result = ['[', GENERATOR_OBJECT._lineBreak];
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
node.elements.forEach (function (element) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [element.type] (element),
',',
GENERATOR_OBJECT._lineBreak
);
});
//remove the last (extra) comma, restore indentation and add whitespace chars & closing bracket
result [result.length - 2] = GENERATOR_OBJECT._lineBreak;
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result [result.length - 1] = GENERATOR_OBJECT._indent;
result.push (']');
return result;
},
AssignmentExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.left.type] (node.left),
GENERATOR_OBJECT._space,
node.operator,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.right.type] (node.right)
];
return result;
},
BinaryExpression: function (node) {
var GENERATOR_OBJECT = this, result;
var left = (node.left.type === 'Identifier' || node.left.type === 'Literal') ?
(GENERATOR_OBJECT [node.left.type] (node.left)) :
['(', GENERATOR_OBJECT [node.left.type] (node.left), ')'];
var right = (node.right.type === 'Identifier' || node.right.type === 'Literal') ?
(GENERATOR_OBJECT [node.right.type] (node.right)) :
['(', GENERATOR_OBJECT [node.right.type] (node.right), ')'];
result = [
left,
GENERATOR_OBJECT._space,
node.operator,
GENERATOR_OBJECT._space,
right
];
return result;
},
CallExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.callee.type] (node.callee),
GENERATOR_OBJECT._space,
'('
];
if (node.arguments.length) {
node.arguments.forEach (function (arg) {
result.push (
GENERATOR_OBJECT [arg.type] (arg),
',',
GENERATOR_OBJECT._space
);
});
result = result.slice (0, -2); //remove trailing comma & space
}
result.push (')');
return result;
},
ConditionalExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.test.type] (node.test),
GENERATOR_OBJECT._space,
'?',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.consequent.type] (node.consequent),
GENERATOR_OBJECT._space,
':',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.alternate.type] (node.alternate)
];
return result;
},
DeclarativeExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.literal.type] (node.literal),
GENERATOR_OBJECT._space,
node.is_constant ? Syntax.constant + GENERATOR_OBJECT._space : '',
node.is_public ? Syntax.public + GENERATOR_OBJECT._space : '',
node.is_private ? Syntax.private + GENERATOR_OBJECT._space : '',
node.is_internal ? Syntax.internal + GENERATOR_OBJECT._space : '',
node.is_memory ? Syntax.memory + GENERATOR_OBJECT._space : '',
node.name
];
return result;
},
DenominationLiteral: function (node) {
return (
node.literal +
this._space +
node.denomination
);
},
Identifier:function (node) {
return node.name;
},
Literal: function (node) {
var GENERATOR_OBJECT = this;
if (node.value === null) {
return Syntax.null;
} else if (node.value && node.value.constructor === RegExp) {
return node.value.toString ();
}
switch (typeof node.value) {
case 'number':
case 'boolean':
return node.value.toString ();
case 'string':
if (isHex (node.value)) {
return node.value;
}
return GENERATOR_OBJECT._quote +
node.value +
GENERATOR_OBJECT._quote;
default:
throw new Error ('Invalid Literal');
}
},
MappingExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.mapping,
GENERATOR_OBJECT._space,
'(',
GENERATOR_OBJECT [node.from.type] (node.from),
GENERATOR_OBJECT._space,
'=>',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.to.type] (node.to),
')'
];
return result;
},
MemberExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
GENERATOR_OBJECT [node.object.type] (node.object)
];
if (node.computed) {
result.push (
GENERATOR_OBJECT._space,
'[',
GENERATOR_OBJECT [node.property.type] (node.property),
']'
);
} else {
var prop = GENERATOR_OBJECT [node.property.type] (node.property);
result.push (
'.',
//Literal wraps strings in quotes.
//We need to remove them to retrieve object.property instead of object.'property'
prop.replace (new RegExp (GENERATOR_OBJECT._quote, 'g'), '')
);
}
return result;
},
NewExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
Syntax.new,
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [node.callee.type] (node.callee),
GENERATOR_OBJECT._space,
'('
];
if (node.arguments.length) {
node.arguments.forEach (function (arg) {
result.push (
GENERATOR_OBJECT [arg.type] (arg),
',',
GENERATOR_OBJECT._space
);
});
result = result.slice (0, -2);
}
result.push (')');
return result;
},
ObjectExpression: function (node) {
var GENERATOR_OBJECT = this, result;
if (!node.properties.length) {
return '{}';
}
GENERATOR_OBJECT._indent = append (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result = [
'{',
GENERATOR_OBJECT._lineBreak
];
node.properties.forEach (function (property) {
result.push (
GENERATOR_OBJECT._indent,
GENERATOR_OBJECT [property.key.type] (property.key),
':',
GENERATOR_OBJECT._space,
GENERATOR_OBJECT [property.value.type] (property.value),
',',
GENERATOR_OBJECT._lineBreak
);
});
result.splice (result.length - 2, 1); //remove the (unnecessary) comma after last value
GENERATOR_OBJECT._indent = removeAppended (GENERATOR_OBJECT._indent, GENERATOR_OBJECT._indentStyle);
result.push (GENERATOR_OBJECT._indent, '}');
return result;
},
SequenceExpression: function (node) {
var GENERATOR_OBJECT = this, result = ['('];
node.expressions.forEach (function (expr) {
result.push (
GENERATOR_OBJECT [expr.type] (expr),
',',
GENERATOR_OBJECT._space
);
});
if (result.length >= 2) {
result = result.slice (0, -2);
}
result.push (')');
return result;
},
ThisExpression: function (node) {
return Syntax.this;
},
Type: function (node) {
var GENERATOR_OBJECT = this, result;
result = isStrictlyObject (node.literal) ?
[GENERATOR_OBJECT [node.literal.type] (node.literal)] :
[node.literal];
for (var i = 0; i < node.members.length; i++) {
result.push (
'.',
node.members [i]
);
}
if (node.array_parts.length) {
result.push (
node.array_parts [0] === null ? '[]' : '[' + node.array_parts [0] + ']'
);
}
return result;
},
UpdateExpression: function (node) {
var GENERATOR_OBJECT = this, result;
result = [
node.prefix ? node.operator : '',
GENERATOR_OBJECT [node.argument.type] (node.argument),
node.prefix ? '' : node.operator
];
return result;
}
};
mergeObjects (CodeGenerator.prototype, CodeGenerator.Expression);
/**
* Main Soltar Object API
* @param {ASTNode} node The AST Node which serves as the root for generating Code. This could be a whole 'Program' itself.
* @param {Object} options User-defined options to customize the code (indentation, spacing, minification, etc.)
* @returns {String} sourceCode The Source Code generated from the given AST Node.
*/
Soltar.generate = function generate (node, options) {
var defaultOptions = options &&
options.format &&
options.format.minify ?
getMinifyOptions () : getDefaultOptions ();
var sourceCode;
if (!isASTNode (node)) {
throw new Error ('Invalid Argument for node');
}
if (options && !isStrictlyObject (options)) {
throw new Error ('Invalid argument for options');
}
//make sure any un-specified options are set to their default values
options = fillGapsDeeply (defaultOptions, options || {});
sourceCode = new CodeGenerator ()
.init (options)
.generate (node);
return flatten (sourceCode);
};
if (typeof window !== 'undefined') { //export to browser
window.Soltar = Soltar;
}
module.exports = Soltar;
},{"./package.json":7,"sol-explore":2}],2:[function(require,module,exports){
/**
*@fileoverview Exposes all the exploration-related functions through main object
*@author Raghav Dua
*/
'use strict';
var SolExplore = {
traverse: require ('./lib/traverse'),
traversalOptions: require ('./lib/traversalOptions'),
Syntax: require ('./lib/syntax'),
version: require ('./package.json').version
};
if (typeof window !== 'undefined') {
window.SolExplore = SolExplore;
}
module.exports = SolExplore;
},{"./lib/syntax":3,"./lib/traversalOptions":4,"./lib/traverse":5,"./package.json":6}],3:[function(require,module,exports){
module.exports = {
'as': 'as',
'break': 'break',
'case': 'case',
'catch': 'catch',
'class': 'class',
'const': 'const',
'constant': 'constant',
'continue': 'continue',
'contract': 'contract',
'debugger': 'debugger',
'default': 'default',
'delete': 'delete',
'do': 'do',
'else': 'else',
'enum': 'enum',
'ether': 'ether',
'event': 'event',
'export': 'export',
'extends': 'extends',
'false': 'false',
'finally': 'finally',
'finney': 'finney',
'for': 'for',
'from': 'from',
'function': 'function',
'get': 'get',
'if': 'if',
'is': 'is',
'indexed': 'indexed',
'instanceof': 'instanceof',
'in': 'in',
'import': 'import',
'internal': 'internal',
'library': 'library',
'mapping': 'mapping',
'memory': 'memory',
'modifier': 'modifier',
'new': 'new',
'null': 'null',
'private': 'private',
'public': 'public',
'return': 'return',
'returns': 'returns',
'set': 'set',
'storage': 'storage',
'struct': 'struct',
'super': 'super',
'switch': 'switch',
'szabo': 'szabo',
'this': 'this',
'throw': 'throw',
'true': 'true',
'try': 'try',
'typeof': 'typeof',
'using': 'using',
'var': 'var',
'void': 'void',
'wei': 'wei',
'while': 'while',
'with': 'with'
};
},{}],4:[function(require,module,exports){
/**
*@fileoverview options that a visitor may include in their enter() or leave() functions to alter normal traversal behavior
*@author Raghav Dua
*/
'use strict';
module.exports = {
STOP_TRAVERSAL: 'stop',
SKIP_NODES_BELOW: 'skip'
};
},{}],5:[function(require,module,exports){
/**
*@fileoverview Depth First Traversal of the given Abstract Syntax Tree
*@author Raghav Dua
*/
'use strict';
var traversalOptions = require ('./traversalOptions');
/**
* Constructor for creating an Element wrapper around node (to bundle other information with it)
* @param {Object} node The node to wrap
* @private
*/
var Element = function (node) {
if (!(this instanceof Element)) {
return new Element (node);
}
this.node = node;
};
/**
* Determine if a given object property is an explorable AST Node
* @param {Object} node The node to check
* @param {String} name Name of the key whose value is this node, to make sure we never explore a node's parent
* @private
*/
function isASTNode (node, name) {
return (
node !== null && //node shouldn't be null
typeof (node) === 'object' && //must be data type object
node.hasOwnProperty ('type') && //a 'type' key must exist in the node
typeof (node.type) === 'string' && //node.type's value must be a string
name !== 'parent' //the key whose value is this entire node must not be 'parent'
);
}
/**
* Constructor for the internal Controller object
* @private
*/
function Controller () {}
/**
* Set the Controller-wide flag
* @param {String} flag The flag to set
* @private
*/
Controller.prototype.notify = function notify (flag) {
this.__flag = flag;
};
/**
* Notify to set the Controller-wide flag for halting traversal
* @private
*/
Controller.prototype.skipNodesBelow = function skip () {
this.notify (traversalOptions.SKIP_NODES_BELOW);
};
/**
* Notify to set the Controller-wide flag for skipping child nodes of the current node
* @private
*/
Controller.prototype.stopTraversal = function stop () {
this.notify (traversalOptions.STOP_TRAVERSAL);
};
/**
* Initialize the state of the internal Controller Object before starting traversal
* @param {object} root The Abstract Syntax Tree object (treated as the AST's root itself)
* @param {Object} visitorActions The object containing enter and leave behaviors
* @private
*/
Controller.prototype.init = function init (root, visitorActions) {
this.root = root;
this.visitorActions = visitorActions;
this.__flag = null;
this.__current = null;
};
/**
* Execute user-provided callback, providing it with 'this' as context
* @param {Function} callback The callback to execute
* @param {Object} element The Element object containing the node currently being entered/left
* @returns {(String|undefined)} result Returns commands sent by the callback (for stopping or skipping)
* @private
*/
Controller.prototype.exec = function exec (callback, element, parentElement) {
var prev, result;
prev = this.__current;
this.__flag = null;
this.__current = element;
if (typeof (callback) === 'function') {
result = callback.call (
this, element.node, parentElement ? parentElement.node : undefined
);
}
this.__current = prev;
return result;
};
/**
* Implementation of the DFS traversal and executing callbacks upon enter & leave phases
* @param {object} root The Abstract Syntax Tree object (treated as the AST's root itself) to traverse
* @param {Object} visitorActions The object containing enter and leave behaviors
* @private
*/
Controller.prototype.traverse = function traverse (root, parent, visitorActions) {
if (!isASTNode (root) ||
this.__flag === traversalOptions.STOP_TRAVERSAL) {
return;
}
//access Controller Object's context inside nested functions (where 'this' may not refer to the main object)
var CTRL_OBJECT = this;
var ret = this.exec (visitorActions.enter, new Element (root), new Element (parent));
if (ret === traversalOptions.STOP_TRAVERSAL) {
this.notify (ret);
return;
} else if (!(ret === traversalOptions.SKIP_NODES_BELOW ||
this.__flag === traversalOptions.SKIP_NODES_BELOW)) {
Object.keys (root).forEach (function (key) {
var child = root [key];
if (isASTNode (child)) {
CTRL_OBJECT.traverse (child, root, visitorActions);
} else if (child && child.constructor === Array) {
child.forEach (function (childItem) {
CTRL_OBJECT.traverse (childItem, root, visitorActions);
});
}
});
}
if (this.__flag !== traversalOptions.STOP_TRAVERSAL) {
this.exec (visitorActions.leave, new Element (root));
}
};
/**
* The single function exposed to the user
* @param {object} ast The Abstract Syntax Tree object to traverse
* @param {Object} visitorEnterOrActions The object containing enter and leave behaviors
*/
module.exports = function (ast, visitorEnterOrActions) {
var visitorActions = {};
if (typeof (visitorEnterOrActions) === 'function') {
visitorActions = {
enter: visitorEnterOrActions
};
} else {
visitorActions.enter = visitorEnterOrActions.enter || function () {};
visitorActions.leave = visitorEnterOrActions.leave || function () {};
}
return new Controller ().traverse (ast, null, visitorActions);
};
},{"./traversalOptions":4}],6:[function(require,module,exports){
module.exports={
"_args": [
[
{
"name": "sol-explore",
"raw": "sol-explore@^1.5.0",
"rawSpec": "^1.5.0",
"scope": null,
"spec": ">=1.5.0 <2.0.0",
"type": "range"
},
"/home/raghav/Desktop/github/soltar"
]
],
"_from": "sol-explore@>=1.5.0 <2.0.0",
"_id": "sol-explore@1.6.2",
"_inCache": true,
"_installable": true,
"_location": "/sol-explore",
"_nodeVersion": "4.2.6",
"_npmOperationalInternal": {
"host": "packages-12-west.internal.npmjs.com",
"tmp": "tmp/sol-explore-1.6.2.tgz_1472483822108_0.5602311752736568"
},
"_npmUser": {
"email": "duaraghav8@gmail.com",
"name": "the-mad-king"
},
"_npmVersion": "3.9.6",
"_phantomChildren": {},
"_requested": {
"name": "sol-explore",
"raw": "sol-explore@^1.5.0",
"rawSpec": "^1.5.0",
"scope": null,
"spec": ">=1.5.0 <2.0.0",
"type": "range"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz",
"_shasum": "43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2",
"_shrinkwrap": null,
"_spec": "sol-explore@^1.5.0",
"_where": "/home/raghav/Desktop/github/soltar",
"author": {
"name": "Raghav Dua"
},
"bugs": {
"url": "https://github.com/duaraghav8/sol-explore/issues"
},
"dependencies": {},
"description": "Traversal functions for solidity-parser generated AST",
"devDependencies": {},
"directories": {},
"dist": {
"shasum": "43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2",
"tarball": "https://registry.npmjs.org/sol-explore/-/sol-explore-1.6.2.tgz"
},
"gitHead": "a56fc36775dc364b69a988e228562e9f385da5d9",
"homepage": "https://github.com/duaraghav8/sol-explore#readme",
"keywords": [
"Abstract-Syntax-Tree",
"Traversal",
"Solidity"
],
"license": "MIT",
"main": "index.js",
"maintainers": [
{
"email": "duaraghav8@gmail.com",
"name": "the-mad-king"
}
],
"name": "sol-explore",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git+https://github.com/duaraghav8/sol-explore.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "1.6.2"
}
},{}],7:[function(require,module,exports){
module.exports={
"name": "soltar",
"version": "2.0.5",
"description": "Generate Solidity Code from solidity-parser's AST",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/duaraghav8/soltar.git"
},
"keywords": [
"Solidity",
"Code-Generation",
"Abstract-Syntax-Tree"
],
"author": "duaraghav8@gmail.com",
"license": "MIT",
"bugs": {
"url": "https://github.com/duaraghav8/soltar/issues"
},
"homepage": "https://github.com/duaraghav8/soltar#readme",
"dependencies": {
"sol-explore": "^1.6.2"
}
}
},{}]},{},[1]);