// Juttle exception classes and related helper functions.

var Base = require('extendable-base');
var _ = require('underscore');
var messages = require('./strings/juttle-error-strings-en-US').error;

// ----- Exception Definitions -----

var errors = {};

// Base class of all Juttle exceptions. Idally, all exceptions thrown by the
// Juttle compiler and runtime would be subclasses of this class, and all other
// exceptions would indicate bugs. But we aren't there yet.
//
// Don't throw this exception directly, use its subclasses and related helpers
// instead.
errors.JuttleError = Base.inherits(Error, {
    name: 'JuttleError',

    initialize: function(message, code, info) {
        this.message = message;
        this.code = code;
        this.info = info;

        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, this.constructor);
        }
    }
});

// Exception thrown when Juttle program parsing fails.
//
// Don't throw this exception directly, use the syntaxError helper instead.
errors.SyntaxError = errors.JuttleError.extend({
    name: 'SyntaxError',
});

// Exception thrown when Juttle program compilation fails. Compilation includes
// everything that happens before points start flowing through the graph (e.g.
// proc initialization).
//
// Don't throw this exception directly, use the compileError helper instead.
errors.CompileError = errors.JuttleError.extend({
    name: 'CompileError',
});

// Exception thrown when Juttle program fails at runtime. Runtime is the time
// when points flow through the graph.
//
// Don't throw this exception directly, use the runtimeError helper instead.
errors.RuntimeError = errors.JuttleError.extend({
    name: 'RuntimeError',
});

// ----- Helpers -----

function messageForCode(code, info) {
    var template = _.template(messages[code], {
        interpolate: /\{\{([^}]*)\}\}/g,
        variable: 'info'
    });

    return template(info);
}

errors.syntaxError = function(code, info) {
    return new errors.SyntaxError(messageForCode(code, info), code, info || {});
};

errors.compileError = function(code, info) {
    return new errors.CompileError(messageForCode(code, info), code, info || {});
};

errors.runtimeError = function(code, info) {
    return new errors.RuntimeError(messageForCode(code, info), code, info || {});
};

// Adds specified location to any Juttle exception thrown when executing
// specified function. If the function does not throw any exception, returns its
// result.
errors.locate = function(fn, location) {
    try {
        return fn();
    } catch (e) {
        if (e instanceof errors.JuttleError && !e.info.location) {
            e.info.location = location;
        }

        throw e;
    }
};

module.exports = errors;

@@ -235,26 +235,8 @@
 --%0A%0A
-var errors = %7B%7D;%0A%0A
 // B
@@ -542,23 +542,20 @@
 nstead.%0A
-errors.
+var 
 JuttleEr
@@ -997,23 +997,20 @@
 nstead.%0A
-errors.
+var 
 SyntaxEr
@@ -1008,34 +1008,28 @@
  SyntaxError
+_
  = 
-errors.
 JuttleError.
@@ -1331,23 +1331,20 @@
 nstead.%0A
-errors.
+var 
 CompileE
@@ -1342,39 +1342,32 @@
  CompileError = 
-errors.
 JuttleError.exte
@@ -1599,23 +1599,20 @@
 nstead.%0A
-errors.
+var 
 RuntimeE
@@ -1618,23 +1618,16 @@
 Error = 
-errors.
 JuttleEr
@@ -1885,23 +1885,25 @@
 fo);%0A%7D%0A%0A
-errors.
+function 
 syntaxEr
@@ -1901,35 +1901,24 @@
  syntaxError
- = function
 (code, info)
@@ -1935,23 +1935,16 @@
 urn new 
-errors.
 SyntaxEr
@@ -1942,24 +1942,25 @@
  SyntaxError
+_
 (messageForC
@@ -1996,26 +1996,27 @@
 %7C %7B%7D);%0A%7D
-;
 %0A%0A
-errors.
+function 
 compileE
@@ -2015,35 +2015,24 @@
 compileError
- = function
 (code, info)
@@ -2049,23 +2049,16 @@
 urn new 
-errors.
 CompileE
@@ -2114,18 +2114,19 @@
 );%0A%7D
-;
 %0A%0A
-errors.
+function 
 runt
@@ -2133,27 +2133,16 @@
 imeError
- = function
 (code, i
@@ -2163,23 +2163,16 @@
 urn new 
-errors.
 RuntimeE
@@ -2224,17 +2224,16 @@
 %7C %7B%7D);%0A%7D
-;
 %0A%0A// Add
@@ -2395,32 +2395,16 @@
 lt.%0A
-errors.locate = 
 function
 (fn,
@@ -2399,16 +2399,23 @@
 function
+ locate
 (fn, loc
@@ -2501,15 +2501,8 @@
 eof 
-errors.
 Jutt
@@ -2607,17 +2607,16 @@
 %0A    %7D%0A%7D
-;
 %0A%0Amodule
@@ -2630,12 +2630,247 @@
 s = 
-errors
+%7B%0A    JuttleError: JuttleError,%0A    SyntaxError: SyntaxError_,%0A    CompileError: CompileError,%0A    RuntimeError: RuntimeError,%0A    syntaxError: syntaxError,%0A    compileError: compileError,%0A    runtimeError: runtimeError,%0A    locate: locate%0A%7D
 ;%0A

Build the module more conventionally