rethinkdbdash
Version:
A Node.js driver for RethinkDB with promises and a connection pool
1,063 lines (912 loc) • 29.2 kB
JavaScript
var helper = require(__dirname+'/helper.js');
var INDENT = 4;
var LIMIT = 80;
var IS_OPERATIONAL = 'isOperational';
var protodef = require(__dirname+'/protodef.js');
var responseTypes = protodef.Response.ResponseType;
var protoErrorType = protodef.Response.ErrorType;
var termTypes = protodef.Term.TermType;
var datumTypes = protodef.Datum.DatumType;
var frameTypes = protodef.Frame.FrameType;
function ReqlDriverError(message, query, secondMessage) {
this.message = this.msg = message;
Error.captureStackTrace(this, ReqlDriverError);
if ((Array.isArray(query) && (query.length > 0)) || (!Array.isArray(query) && query != null)) {
if ((this.message.length > 0) && (this.message[this.message.length-1] === '.')) {
this.message = this.message.slice(0, this.message.length-1);
}
this.message += ' after:\n';
var backtrace = generateBacktrace(query, 0, null, [], {indent: 0, extra: 0});
this.message += backtrace.str;
}
else {
if (this.message[this.message.length-1] !== '?') this.message += '.';
}
if (secondMessage) this.message += '\n'+secondMessage;
};
ReqlDriverError.prototype = new Error();
ReqlDriverError.prototype.name = 'ReqlDriverError';
ReqlDriverError.prototype.setOperational = function() {
this[IS_OPERATIONAL] = true;
return this;
};
module.exports.ReqlDriverError = ReqlDriverError;
function ReqlServerError(message, query) {
this.message = this.msg = message;
Error.captureStackTrace(this, ReqlServerError);
if ((Array.isArray(query) && (query.length > 0)) || (!Array.isArray(query) && query != null)) {
if ((this.message.length > 0) && (this.message[this.message.length-1] === '.')) {
this.message = this.message.slice(0, this.message.length-1);
}
this.message += ' for:\n';
var backtrace = generateBacktrace(query, 0, null, [], {indent: 0, extra: 0});
this.message += backtrace.str;
}
else {
if (this.message[this.message.length-1] !== '?') this.message += '.';
}
};
ReqlServerError.prototype = new Error();
ReqlServerError.prototype.name = 'ReqlServerError';
ReqlServerError.prototype[IS_OPERATIONAL] = true;
module.exports.ReqlServerError = ReqlServerError;
function ReqlRuntimeError(message, query, frames) {
this.message = this.msg = message;
Error.captureStackTrace(this, ReqlRuntimeError);
if ((query != null) && (frames)) {
if ((this.message.length > 0) && (this.message[this.message.length-1] === '.')) {
this.message = this.message.slice(0, this.message.length-1);
}
this.message += ' in:\n';
frames = frames.b;
if (frames) this.frames = frames.slice(0);
//this.frames = JSON.stringify(frames, null, 2);
var backtrace = generateBacktrace(query, 0, null, frames, {indent: 0, extra: 0});
var queryLines = backtrace.str.split('\n');
var carrotLines = backtrace.car.split('\n');
for(var i=0; i<queryLines.length; i++) {
this.message += queryLines[i]+'\n';
if (carrotLines[i].match(/\^/)) {
var pos = queryLines[i].match(/[^\s]/);
if ((pos) && (pos.index)) {
this.message += space(pos.index)+carrotLines[i].slice(pos.index)+'\n';
}
else {
this.message += carrotLines[i]+'\n';
}
}
}
}
//this.query = JSON.stringify(query, null, 2);
};
ReqlRuntimeError.prototype = new Error();
ReqlRuntimeError.prototype.name = 'ReqlRuntimeError';
ReqlRuntimeError.prototype.setName = function(type) {
switch(type) {
case protoErrorType.INTERNAL:
this.name = 'ReqlInternalError';
break;
case protoErrorType.RESOURCE_LIMIT:
this.name = 'ReqlResourceError';
break;
case protoErrorType.QUERY_LOGIC:
this.name = 'ReqlLogicError';
break;
case protoErrorType.OP_FAILED:
this.name = 'ReqlOpFailedError';
break;
case protoErrorType.OP_INDETERMINATE:
this.name = 'ReqlOpIndeterminateError';
break;
case protoErrorType.USER:
this.name = 'ReqlUserError';
break;
//default: // Do nothing
}
}
ReqlRuntimeError.prototype[IS_OPERATIONAL] = true;
module.exports.ReqlRuntimeError = ReqlRuntimeError;
function ReqlCompileError(message, query, frames) {
this.message = message;
Error.captureStackTrace(this, ReqlCompileError);
if ((query != null) && (frames)) {
if ((this.message.length > 0) && (this.message[this.message.length-1] === '.')) {
this.message = this.message.slice(0, this.message.length-1);
}
this.message += ' in:\n';
frames = frames.b;
if (frames) this.frames = frames.slice(0);
//this.frames = JSON.stringify(frames, null, 2);
var backtrace = generateBacktrace(query, 0, null, frames, {indent: 0, extra: 0});
var queryLines = backtrace.str.split('\n');
var carrotLines = backtrace.car.split('\n');
for(var i=0; i<queryLines.length; i++) {
this.message += queryLines[i]+'\n';
if (carrotLines[i].match(/\^/)) {
var pos = queryLines[i].match(/[^\s]/);
if ((pos) && (pos.index)) {
this.message += space(pos.index)+carrotLines[i].slice(pos.index)+'\n';
}
else {
this.message += carrotLines[i]+'\n';
}
}
}
}
};
ReqlCompileError.prototype = new Error();
ReqlCompileError.prototype.name = 'ReqlCompileError';
ReqlCompileError.prototype[IS_OPERATIONAL] = true;
module.exports.ReqlCompileError = ReqlCompileError;
function ReqlClientError(message) {
this.message = message;
Error.captureStackTrace(this, ReqlClientError);
};
ReqlClientError.prototype = new Error();
ReqlClientError.prototype.name = 'ReqlClientError';
ReqlClientError.prototype[IS_OPERATIONAL] = true;
module.exports.ReqlClientError = ReqlClientError;
var _constants = {
MONDAY: true,
TUESDAY: true,
WEDNESDAY: true,
THURSDAY: true,
FRIDAY: true,
SATURDAY: true,
SUNDAY: true,
JANUARY: true,
FEBRUARY: true,
MARCH: true,
APRIL: true,
MAY: true,
JUNE: true,
JULY: true,
AUGUST: true,
SEPTEMBER: true,
OCTOBER: true,
NOVEMBER: true,
DECEMBER: true,
MINVAL: true,
MAXVAL: true,
}
var constants = {};
for(var key in _constants) {
constants[termTypes[key]] = true;
}
var _nonPrefix = {
DB: true,
DB_CREATE: true,
DB_LIST: true,
DB_DROP: true,
JS: true,
NOW: true,
TIME: true,
EPOCH_TIME: true,
ISO8601: true,
BRANCH: true,
JAVASCRIPT: true,
ERROR: true,
MAKE_ARRAY: true,
JSON: true,
ARGS: true,
HTTP: true,
RANDOM: true,
BINARY: true,
OBJECT: true,
CIRCLE: true,
GEOJSON: true,
POINT: true,
LINE: true,
POLYGON: true,
UUID: true,
DESC: true,
ASC: true,
RANGE: true,
LITERAL: 'true'
}
var nonPrefix = {};
for(var key in _nonPrefix) {
nonPrefix[termTypes[key]] = true;
}
// Constants are also in nonPrefix
for(var key in _constants) {
nonPrefix[termTypes[key]] = true;
}
var _typeToString = {
DB: 'db',
DB_CREATE: 'dbCreate',
DB_LIST: 'dbList',
DB_DROP: 'dbDrop',
TABLE_CREATE: 'tableCreate',
TABLE_LIST: 'tableList',
TABLE_DROP: 'tableDrop',
TABLE: 'table',
INDEX_CREATE: 'indexCreate',
INDEX_DROP: 'indexDrop',
INDEX_LIST: 'indexList',
INDEX_WAIT: 'indexWait',
INDEX_STATUS: 'indexStatus',
INSERT: 'insert',
UPDATE: 'update',
REPLACE: 'replace',
DELETE: 'delete',
SYNC: 'sync',
GET: 'get',
GET_ALL: 'getAll',
BETWEEN: 'between',
FILTER: 'filter',
INNER_JOIN: 'innerJoin',
OUTER_JOIN: 'outerJoin',
EQ_JOIN: 'eqJoin',
ZIP: 'zip',
MAP: 'map',
WITH_FIELDS: 'withFields',
CONCAT_MAP: 'concatMap',
ORDER_BY: 'orderBy',
DESC: 'desc',
ASC: 'asc',
SKIP: 'skip',
LIMIT: 'limit',
SLICE: 'slice',
NTH: 'nth',
OFFSETS_OF: 'offsetsOf',
IS_EMPTY: 'isEmpty',
UNION: 'union',
SAMPLE: 'sample',
REDUCE: 'reduce',
COUNT: 'count',
SUM: 'sum',
AVG: 'avg',
MIN: 'min',
MAX: 'max',
FOLD: 'fold',
OBJECT: 'object',
DISTINCT: 'distinct',
GROUP: 'group',
UNGROUP: 'ungroup',
CONTAINS: 'contains',
IMPLICIT_VAR: 'row',
PLUCK: 'pluck',
WITHOUT: 'without',
MERGE: 'merge',
APPEND: 'append',
PREPEND: 'prepend',
DIFFERENCE: 'difference',
SET_INSERT: 'setInsert',
SET_UNION: 'setUnion',
SET_INTERSECTION: 'setIntersection',
SET_DIFFERENCE: 'setDifference',
HAS_FIELDS: 'hasFields',
INSERT_AT: 'insertAt',
SPLICE_AT: 'spliceAt',
DELETE_AT: 'deleteAt',
CHANGE_AT: 'changeAt',
KEYS: 'keys',
VALUES: 'values',
MATCH: 'match',
UPCASE: 'upcase',
DOWNCASE: 'downcase',
ADD: 'add',
SUB: 'sub',
MUL: 'mul',
DIV: 'div',
MOD: 'mod',
AND: 'and',
OR: 'or',
EQ: 'eq',
NE: 'ne',
GT: 'gt',
GE: 'ge',
LT: 'lt',
LE: 'le',
NOT: 'not',
FLOOR: 'floor',
CEIL: 'ceil',
ROUND: 'round',
NOW: 'now',
TIME: 'time',
EPOCH_TIME: 'epochTime',
ISO8601: 'ISO8601',
IN_TIMEZONE: 'inTimezone',
TIMEZONE: 'timezone',
DURING: 'during',
DATE: 'date',
TIME_OF_DAY: 'timeOfDay',
YEAR: 'year',
MONTH: 'month',
DAY: 'day',
DAY_OF_WEEK: 'dayOfWeek',
DAY_OF_YEAR: 'dayOfYear',
HOURS: 'hours',
MINUTES: 'minutes',
SECONDS: 'seconds',
TO_ISO8601: 'toISO8601',
TO_EPOCH_TIME: 'toEpochTime',
FUNCALL: 'do',
BRANCH: 'branch',
FOR_EACH: 'forEach',
ERROR: 'error',
DEFAULT: 'default',
JAVASCRIPT: 'js',
COERCE_TO: 'coerceTo',
TYPE_OF: 'typeOf',
INFO: 'info',
JSON: 'json',
ARGS: 'args',
HTTP: 'http',
RANDOM: 'random',
CHANGES: 'changes',
BINARY: 'binary',
INDEX_RENAME: 'indexRename',
CIRCLE: 'circle',
DISTANCE: 'distance',
FILL: 'fill',
GEOJSON: 'geojson',
TO_GEOJSON: 'toGeojson',
GET_INTERSECTING: 'getIntersecting',
GET_NEAREST: 'getNearest',
INCLUDES: 'includes',
INTERSECTS: 'intersects',
LINE: 'line',
POINT: 'point',
POLYGON: 'polygon',
POLYGON_SUB: 'polygonSub',
UUID: 'uuid',
RANGE: 'range',
TO_JSON_STRING: 'toJSON',
CONFIG: 'config',
STATUS: 'status',
WAIT: 'wait',
RECONFIGURE: 'reconfigure',
REBALANCE: 'rebalance',
GRANT: 'grant',
SPLIT: 'split',
LITERAL: 'literal',
MONDAY: 'monday',
TUESDAY: 'tuesday',
WEDNESDAY: 'wednesday',
THURSDAY: 'thursday',
FRIDAY: 'friday',
SATURDAY: 'saturday',
SUNDAY: 'sunday',
JANUARY: 'january',
FEBRUARY: 'february',
MARCH: 'march',
APRIL: 'april',
MAY: 'may',
JUNE: 'june',
JULY: 'july',
AUGUST: 'august',
SEPTEMBER: 'september',
OCTOBER: 'october',
NOVEMBER: 'november',
DECEMBER: 'december' ,
MINVAL: 'minval',
MAXVAL: 'maxval',
}
var typeToString = {};
for(var key in _typeToString) {
typeToString[termTypes[key]] = _typeToString[key];
}
var _noPrefixOptargs = {
ISO8601: true,
}
var noPrefixOptargs = {};
for(var key in _noPrefixOptargs) {
noPrefixOptargs[termTypes[key]] = true;
}
var _specialType = {
DATUM: function(term, index, father, frames, options, optarg) {
optarg = optarg || false;
var underline = Array.isArray(frames) && (frames.length === 0);
var currentFrame, backtrace;
if (Array.isArray(frames)) currentFrame = frames.shift();
var result = {
str: '',
car: ''
}
if ((helper.isPlainObject(term)) && (term.$reql_type$ === 'BINARY')) {
carify(result, 'r.binary(<Buffer>)', underline);
return result;
}
if ((index === 0) && ((father == null) || (!nonPrefix[father[0]]))) carify(result, 'r.expr(', underline)
if (typeof term === 'string' ) {
carify(result, '"'+term+'"', underline);
}
else if (helper.isPlainObject(term)) {
var totalKeys = Object.keys(term).length;
if (totalKeys === 0) {
carify(result, '{}', underline);
}
else {
carify(result, '{\n', underline);
var countKeys = 0;
var extraToRemove = options.extra;
options.indent += INDENT+options.extra;
options.extra = 0;
for(var key in term) {
countKeys++;
//if (!((father) && (Array.isArray(father[2])) && (Object.keys(father[2]).length > 0))) options.extra = 0;
if (optarg) {
carify(result, space(options.indent)+camelCase(key)+': ', underline);
}
else {
carify(result, space(options.indent)+key+': ', underline);
}
if ((currentFrame != null) && (currentFrame === key)) {
backtrace = generateBacktrace(term[key], i, term, frames, options);
}
else {
backtrace = generateBacktrace(term[key], i, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
if (countKeys !== totalKeys) {
carify(result, ',\n', underline);
}
}
options.indent -= INDENT+extraToRemove;
carify(result, '\n'+space(options.indent+extraToRemove)+'}', underline);
}
}
else if (Array.isArray(term)) {
carify(result, '[', underline);
for(var i=0; i<term.length; i++) {
if ((currentFrame != null) && (currentFrame === i)) {
backtrace = generateBacktrace(term[i], i, term, frames, options);
}
else {
backtrace = generateBacktrace(term[i], i, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
}
carify(result, ']', underline);
}
else {
carify(result, ''+term, underline);
}
if ((index === 0) && ((father == null) || (!nonPrefix[father[0]]))) carify(result, ')', underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
TABLE: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
if ((term.length === 1) || (term[1].length === 0) || (term[1][0][0] !== termTypes.DB)) {
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
carify(result, 'r.'+typeToString[term[0]]+'(', underline);
if (Array.isArray(term[1])) {
for(var i=0; i<term[1].length; i++) {
if (i !==0) result.str += ', ';
if ((currentFrame != null) && (currentFrame === 1)) {
// +1 for index because it's like if there was a r.db(...) before .table(...)
backtrace = generateBacktrace(term[1][i], i+1, term, frames, options)
}
else {
backtrace = generateBacktrace(term[1][i], i+1, term, null, options)
}
result.str += backtrace.str;
result.car += backtrace.car
}
}
backtrace = makeOptargs(term, i, term, frames, options, currentFrame)
result.str += backtrace.str;
result.car += backtrace.car;
carify(result, ')', underline);
if (underline) result.car = result.str.replace(/./g, '^');
}
else {
backtrace = generateNormalBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
return result;
},
GET_FIELD: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if ((currentFrame != null) && (currentFrame === 0)) {
backtrace = generateBacktrace(term[1][0], 0, term, frames, options)
}
else {
backtrace = generateBacktrace(term[1][0], 0, term, null, options)
}
result.str = backtrace.str;
result.car = backtrace.car;
carify(result, '(', underline);
if ((currentFrame != null) && (currentFrame === 1)) {
backtrace = generateBacktrace(term[1][1], 1, term, frames, options)
}
else {
backtrace = generateBacktrace(term[1][1], 1, term, null, options)
}
result.str += backtrace.str;
result.car += backtrace.car;
carify(result, ')', underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
MAKE_ARRAY: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
};
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if ((index === 0) && ((father == null) || (!nonPrefix[father[0]]))) carify(result, 'r.expr(', underline)
if (!((options) && (options.noBracket))) {
carify(result, '[', underline);
}
for(var i=0; i<term[1].length; i++) {
if (i !== 0) {
carify(result, ', ', underline);
}
if ((currentFrame != null) && (currentFrame === i)) {
backtrace = generateBacktrace(term[1][i], i, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][i], i, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
}
if (!((options) && (options.noBracket))) {
carify(result, ']', underline);
}
if ((index === 0) && ((father == null) || (!nonPrefix[father[0]]))) {
carify(result, ')', underline);
}
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
FUNC: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
};
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if ((term[1][0][1].length === 1) && (helper.hasImplicit(term[1][1]))) {
if ((currentFrame != null) && (currentFrame === 1)) {
backtrace = generateBacktrace(term[1][1], 1, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][1], 1, term, null, options);
}
result.str = backtrace.str;
result.car = backtrace.car;
}
else {
carify(result, 'function(', underline);
for(var i=0; i<term[1][0][1].length; i++) {
if (i !== 0) {
carify(result, ', ', underline);
}
carify(result, 'var_'+term[1][0][1][i], underline);
}
options.indent += INDENT+options.extra;
var extraToRemove = options.extra;
options.extra = 0;
//if (!((Array.isArray(term[2])) && (term[2].length > 0))) options.extra = 0;
carify(result, ') {\n'+space(options.indent)+'return ', underline);
if ((currentFrame != null) && (currentFrame === 1)) {
backtrace = generateBacktrace(term[1][1], 1, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][1], 1, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
options.indent -= INDENT+extraToRemove;
options.extra = extraToRemove;
carify(result, '\n'+space(options.indent+extraToRemove)+'}', underline);
}
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
VAR: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
carify(result, 'var_'+term[1][0], underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
FUNCALL: function(term, index, father, frames, options) {
// The syntax is args[1].do(args[0])
var result = {
str: '',
car: ''
};
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if (term[1].length === 2) {
if ((currentFrame != null) && (currentFrame === 1)) {
backtrace = generateBacktrace(term[1][1], 0, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][1], 0, term, null, options);
}
result.str = backtrace.str;
result.car = backtrace.car;
carify(result, '.do(', underline);
}
else {
carify(result, 'r.do(', underline);
for(var i=1; i<term[1].length; i++) {
if ((currentFrame != null) && (currentFrame === i)) {
backtrace = generateBacktrace(term[1][i], i, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][i], i, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
if (i !== term[1].length) {
carify(result, ', ' , underline);
}
}
}
if ((currentFrame != null) && (currentFrame === 0)) {
backtrace = generateBacktrace(term[1][0], 0, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][0], 0, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
carify(result, ')', underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
IMPLICIT_VAR: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
carify(result, 'r.row', underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
},
WAIT: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
if (term.length === 1 || term[1].length === 0) {
backtrace = generateWithoutPrefixBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
else {
backtrace = generateNormalBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
return result;
},
MAP: function(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, underline, currentFrame;
if (term.length > 1 && term[1].length > 2) {
backtrace = generateWithoutPrefixBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
else {
backtrace = generateNormalBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
return result;
},
}
_specialType.TABLE_CREATE = _specialType.TABLE;
_specialType.TABLE_DROP = _specialType.TABLE;
_specialType.TABLE_LIST = _specialType.TABLE;
_specialType.RECONFIGURE = _specialType.WAIT;
_specialType.REBALANCE = _specialType.WAIT;
_specialType.BRACKET = _specialType.GET_FIELD;
var specialType = {};
for(var key in _specialType) {
specialType[termTypes[key]] = _specialType[key];
}
function space(n) {
return new Array(n+1).join(' ');
}
function carify(result, str, underline) {
if (underline === true) {
result.str += str;
result.car += str.replace(/[^\n]/g, '^');
}
else {
result.str += str;
result.car += str.replace(/[^\n]/g, ' ');
}
}
function makeOptargs(term, index, father, frames, options, currentFrame) {
var result = {
str: '',
car: ''
}
var backtrace, currentFrame, underline;
if (helper.isPlainObject(term[2])) {
//if ((currentFrame != null) && (frames != null)) frames.unshift(currentFrame);
//underline = Array.isArray(frames) && (frames.length === 0);
var underline = false;
//if (Array.isArray(frames)) currentFrame = frames.shift();
// This works before there is no prefix term than can be called with no normal argument but with an optarg
if (Array.isArray(term[1]) && (term[1].length > 1)) {
carify(result, ', ' , underline);
}
else if (Array.isArray(term[1]) && (term[1].length > 0) && (noPrefixOptargs[term[0]])) {
carify(result, ', ' , underline);
}
backtrace = specialType[termTypes.DATUM](term[2], index, term[2], frames, options, true);
result.str += backtrace.str;
result.car += backtrace.car;
if (underline) result.car = result.str.replace(/./g, '^');
}
return result;
}
function generateNormalBacktrace(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, currentFrame, underline;
//if (term[1]) {
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if ((currentFrame != null) && (currentFrame === 0)) {
backtrace = generateBacktrace(term[1][0], 0, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][0], 0, term, null, options);
}
result.str = backtrace.str;
result.car = backtrace.car;
var lines = backtrace.str.split('\n');
var line = lines[lines.length-1];
var pos = line.match(/[^\s]/);
pos = (pos) ? pos.index : 0;
if (line.length-pos > LIMIT) {
if (options.extra === 0) options.extra += INDENT;
carify(result, '\n'+space(options.indent+options.extra) , underline);
}
carify(result, '.'+typeToString[term[0]]+'(' , underline);
options.indent += options.extra;
var extraToRemove = options.extra;
options.extra = 0;
for(var i=1; i<term[1].length; i++) {
if (i !== 1) {
carify(result, ', ' , underline);
}
if ((currentFrame != null) && (currentFrame === i)) {
backtrace = generateBacktrace(term[1][i], i, term, frames, options);
}
else {
backtrace = generateBacktrace(term[1][i], i, term, null, options);
}
result.str += backtrace.str;
result.car += backtrace.car;
}
backtrace = makeOptargs(term, i, term, frames, options, currentFrame)
result.str += backtrace.str;
result.car += backtrace.car;
options.indent -= extraToRemove;
options.extra = extraToRemove;
carify(result, ')' , underline);
if (underline) result.car = result.str.replace(/./g, '^');
/*
}
else {
throw new Error('The driver should never enter this condition. Please report the query to the developers -- End 1 --\n'+JSON.stringify(term, null, 2))
}
*/
return result;
}
function generateWithoutPrefixBacktrace(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, currentFrame, underline;
var underline = Array.isArray(frames) && (frames.length === 0);
if (Array.isArray(frames)) currentFrame = frames.shift();
if (constants[term[0]]) {
carify(result, 'r.'+typeToString[term[0]], underline);
return result;
}
carify(result, 'r.'+typeToString[term[0]]+'(', underline);
if (Array.isArray(term[1])) {
for(var i=0; i<term[1].length; i++) {
if (i !== 0) carify(result, ', ', underline)
if ((currentFrame != null) && (currentFrame === i)) {
backtrace = generateBacktrace(term[1][i], i, term, frames, options)
}
else {
backtrace = generateBacktrace(term[1][i], i, term, null, options)
}
result.str += backtrace.str;
result.car += backtrace.car;
}
}
backtrace = makeOptargs(term, i, term, frames, options, currentFrame)
result.str += backtrace.str;
result.car += backtrace.car;
carify(result, ')', underline);
if (underline) result.car = result.str.replace(/./g, '^');
return result;
}
function generateBacktrace(term, index, father, frames, options) {
var result = {
str: '',
car: ''
}
var backtrace, currentFrame, underline;
// frames = null -> do not underline
// frames = [] -> underline
if (Array.isArray(term)) {
if (term.length === 0) {
var underline = Array.isArray(frames) && (frames.length === 0);
carify(result, 'undefined', underline);
}
else if (specialType[term[0]]) {
backtrace = specialType[term[0]](term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
else if (nonPrefix[term[0]]) {
backtrace = generateWithoutPrefixBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
else { // normal type -- this.<method>( this.args... )
backtrace = generateNormalBacktrace(term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
}
else if (term !== undefined) {
backtrace = specialType[termTypes.DATUM](term, index, father, frames, options);
result.str = backtrace.str;
result.car = backtrace.car;
}
else {
//throw new Error('The driver should never enter this condition. Please report the query to the developers -- End 2')
}
return result;
}
function camelCase(str) {
return str.replace(/_(.)/g, function (m, char) { return char.toUpperCase() });
}
module.exports.generateBacktrace = generateBacktrace;
module.exports.setOperational = function(error) {
error[IS_OPERATIONAL] = true;
return error;
};