/**

* Serenade.js JavaScript Framework v0.5.0
* Revision: bcda813708
* http://github.com/elabs/serenade.js
*
* Copyright 2011, Jonas Nicklas, Elabs AB
* Released under the MIT License
*/

(function(root) {

/* Jison generated parser */

var parser = (function(){ var parser = {trace: function trace() { }, yy: {}, symbols_: {“error”:2,“Root”:3,“ChildList”:4,“ElementIdentifier”:5,“AnyIdentifier”:6,“#”:7,“.”:8,“Element”:9,“”:11,“PropertyList”:12,“WHITESPACE”:13,“Text”:14,“INDENT”:15,“OUTDENT”:16,“TextList”:17,“Bound”:18,“STRING_LITERAL”:19,“Child”:20,“TERMINATOR”:21,“IfInstruction”:22,“Instruction”:23,“Helper”:24,“Property”:25,“=”:26,“!”:27,“:”:28,“-”:29,“VIEW”:30,“COLLECTION”:31,“UNLESS”:32,“IN”:33,“IDENTIFIER”:34,“IF”:35,“ElseInstruction”:36,“ELSE”:37,“@”:38,“$accept”:0,“$end”:1}, terminals_: {2:“error”,7:“#”,8:“.”,10:“”,13:“WHITESPACE”,15:“INDENT”,16:“OUTDENT”,19:“STRING_LITERAL”,21:“TERMINATOR”,26:“=”,27:“!”,28:“:”,29:“-”,30:“VIEW”,31:“COLLECTION”,32:“UNLESS”,33:“IN”,34:“IDENTIFIER”,35:“IF”,37:“ELSE”,38:“@”}, productions_: [0,,[3,1],,[5,3],,[5,2],,[9,1],,[9,4],,[9,4],,[17,3],,[14,1],,[4,3],,[20,1],,[20,1],,[12,1],,[25,3],,[25,4],,[25,3],,[23,5],,[23,5],,[23,5],,[24,3],,[24,4],,[22,4],,[36,6],,[6,1],,[6,1],,[6,1],,[18,1]], performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {

var $0 = $$.length - 1; switch (yystate) { case 1:this.$ = null; break; case 2:return this.$ break; case 3:this.$ = {

  name: $$[$0],
  classes: []
};

break; case 4:this.$ = {

  name: $$[$0-2],
  id: $$[$0],
  classes: []
};

break; case 5:this.$ = {

  name: 'div',
  id: $$[$0],
  classes: []
};

break; case 6:this.$ = {

  name: 'div',
  classes: [$$[$0]]
};

break; case 7:this.$ = (function () {

  $$[$0-2].classes.push($$[$0]);
  return $$[$0-2];
}());

break; case 8:this.$ = {

  name: $$[$0].name,
  id: $$[$0].id,
  classes: $$[$0].classes,
  properties: [],
  children: [],
  type: 'element'
};

break; case 9:this.$ = $$[$0-2]; break; case 10:this.$ = (function () {

  $$[$0-3].properties = $$[$0-1];
  return $$[$0-3];
}());

break; case 11:this.$ = (function () {

  $$[$0-2].children = $$[$0-2].children.concat($$[$0]);
  return $$[$0-2];
}());

break; case 12:this.$ = (function () {

  $$[$0-3].children = $$[$0-3].children.concat($$[$0-1]);
  return $$[$0-3];
}());

break; case 13:this.$ = [$$[$0]]; break; case 14:this.$ = $$[$0-2].concat($$); break; case 15:this.$ = {

  type: 'text',
  value: $$[$0],
  bound: true
};

break; case 16:this.$ = {

  type: 'text',
  value: $$[$0],
  bound: false
};

break; case 17:this.$ = [].concat($$); break; case 18:this.$ = $$[$0-2].concat($$); break; case 19:this.$ = $$[$0]; break; case 20:this.$ = $$[$0]; break; case 21:this.$ = $$[$0]; break; case 22:this.$ = $$[$0]; break; case 23:this.$ = $$[$0]; break; case 24:this.$ = [$$[$0]]; break; case 25:this.$ = $$[$0-2].concat($$); break; case 26:this.$ = {

  name: $$[$0-2],
  value: $$[$0],
  bound: true,
  scope: 'attribute'
};

break; case 27:this.$ = {

  name: $$[$0-2],
  value: $$[$0],
  bound: true,
  scope: 'attribute'
};

break; case 28:this.$ = {

  name: $$[$0-3],
  value: $$[$0-1],
  bound: true,
  scope: 'attribute',
  preventDefault: true
};

break; case 29:this.$ = {

  name: $$[$0-3],
  value: $$[$0-1],
  bound: true,
  scope: 'attribute',
  preventDefault: true
};

break; case 30:this.$ = {

  name: $$[$0-2],
  value: $$[$0],
  bound: false,
  scope: 'attribute'
};

break; case 31:this.$ = (function () {

  $$[$0].scope = $$[$0-2];
  return $$[$0];
}());

break; case 32:this.$ = {

  children: [],
  type: 'view',
  argument: $$[$0]
};

break; case 33:this.$ = {

  children: [],
  type: 'view',
  argument: $$[$0],
  bound: true
};

break; case 34:this.$ = {

  children: [],
  type: 'collection',
  argument: $$[$0]
};

break; case 35:this.$ = {

  children: [],
  type: 'unless',
  argument: $$[$0]
};

break; case 36:this.$ = {

  children: [],
  type: 'in',
  argument: $$[$0]
};

break; case 37:this.$ = (function () {

  $$[$0-3].children = $$[$0-1];
  return $$[$0-3];
}());

break; case 38:this.$ = {

  command: $$[$0],
  "arguments": [],
  children: [],
  type: 'helper'
};

break; case 39:this.$ = (function () {

  $$[$0-2]["arguments"].push($$[$0]);
  return $$[$0-2];
}());

break; case 40:this.$ = (function () {

  $$[$0-3].children = $$[$0-1];
  return $$[$0-3];
}());

break; case 41:this.$ = {

  children: [],
  type: 'if',
  argument: $$[$0]
};

break; case 42:this.$ = (function () {

  $$[$0-3].children = $$[$0-1];
  return $$[$0-3];
}());

break; case 43:this.$ = (function () {

  $$[$0-1]["else"] = $$[$0];
  return $$[$0-1];
}());

break; case 44:this.$ = {

  "arguments": [],
  children: $$[$0-1],
  type: 'else'
};

break; case 45:this.$ = $$[$0]; break; case 46:this.$ = $$[$0]; break; case 47:this.$ = $$[$0]; break; case 48:this.$ = $$[$0]; break; case 49:this.$ = $$[$0]; break; case 50:this.$ = $$[$0]; break; case 51:this.$ = $$[$0]; break; case 52:this.$ = (function () {}()); break; } }, table: [{1:,3:1,4:2,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{1:},{1:,21:},{1:,16:,21:},{1:,10:,13:,15:,16:,21:},{1:,15:,16:,21:,29:,36:29},{1:,15:,16:,21:},{1:,13:,15:,16:,21:},{1:,13:,16:,21:},{1:,8:,10:,13:,15:,16:,21:},{13:},{1:,13:,16:,21:},{1:,7:,8:,10:,13:,15:,16:,21:},{6:38,30:,31:,32:,33:,34:,35:},{6:39,30:,31:,32:,33:,34:,35:},{1:,10:,13:,15:,16:,21:},{1:,10:,13:,15:,16:,21:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,7:,8:,10:,11:,13:,15:,16:,21:,26:,27:,28:,29:},{1:,6:40,10:,11:,13:,15:,16:,21:,27:,29:,30:,31:,32:,33:,34:,35:},{5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:41,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{6:45,11:,12:43,25:44,30:,31:,32:,33:,34:,35:},{14:46,18:15,19:,38:},{4:47,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{4:48,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{1:,15:,16:,21:,29:},{13:},{4:50,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{14:51,18:15,19:,38:},{4:52,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{14:53,18:15,19:,38:},{6:54,30:,31:,32:,33:,34:,35:},{30:,31:,32:,33:,34:,35:},{6:61,30:,31:,32:,33:,34:,35:},{1:,8:,10:,13:,15:,16:,21:},{1:,8:,10:,13:,15:,16:,21:},{1:,10:,11:,13:,15:,16:,21:,27:,29:},{1:,16:,21:},{1:,10:,13:,15:,16:,21:},{11:,13:},{11:,13:},{26:,28:},{1:,10:,13:,15:,16:,21:},{16:,21:},{16:,21:},{37:},{16:,21:},{1:,13:,15:,16:,21:},{16:,21:},{1:,13:,16:,21:},{1:,8:,10:,13:,15:,16:,21:},{13:},{13:},{13:},{13:},{13:},{1:,13:,15:,16:,21:},{1:,8:,10:,13:,15:,16:,21:},{1:,10:,13:,15:,16:,21:},{6:45,25:76,30:,31:,32:,33:,34:,35:},{6:77,18:78,19:,30:,31:,32:,33:,34:,35:,38:},{6:45,25:80,30:,31:,32:,33:,34:,35:},{1:,10:,13:,15:,16:,21:},{1:,15:,16:,21:,29:},{15:},{1:,15:,16:,21:},{1:,13:,15:,16:,21:},{18:82,38:},{18:84,19:,38:},{18:85,38:},{18:86,38:},{18:87,38:},{11:,13:},{11:,13:,27:},{11:,13:,27:},{11:,13:},{11:,13:},{4:90,5:9,6:12,7:,8:,9:4,14:11,17:8,18:15,19:,20:3,22:5,23:6,24:7,29:,30:,31:,32:,33:,34:,35:,38:},{1:,15:,16:,21:,29:},{1:,15:,16:,21:},{1:,15:,16:,21:},{1:,15:,16:,21:},{1:,15:,16:,21:},{1:,15:,16:,21:},{11:,13:},{11:,13:},{16:,21:},{1:,15:,16:,21:,29:}], defaultActions: {}, parseError: function parseError(str, hash) {

throw new Error(str);

}, parse: function parse(input) {

var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
this.lexer.setInput(input);
this.lexer.yy = this.yy;
this.yy.lexer = this.lexer;
this.yy.parser = this;
if (typeof this.lexer.yylloc == "undefined")
    this.lexer.yylloc = {};
var yyloc = this.lexer.yylloc;
lstack.push(yyloc);
var ranges = this.lexer.options && this.lexer.options.ranges;
if (typeof this.yy.parseError === "function")
    this.parseError = this.yy.parseError;
function popStack(n) {
    stack.length = stack.length - 2 * n;
    vstack.length = vstack.length - n;
    lstack.length = lstack.length - n;
}
function lex() {
    var token;
    token = self.lexer.lex() || 1;
    if (typeof token !== "number") {
        token = self.symbols_[token] || token;
    }
    return token;
}
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
    state = stack[stack.length - 1];
    if (this.defaultActions[state]) {
        action = this.defaultActions[state];
    } else {
        if (symbol === null || typeof symbol == "undefined") {
            symbol = lex();
        }
        action = table[state] && table[state][symbol];
    }
    if (typeof action === "undefined" || !action.length || !action[0]) {
        var errStr = "";
    }
    if (action[0] instanceof Array && action.length > 1) {
        throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
    }
    switch (action[0]) {
    case 1:
        stack.push(symbol);
        vstack.push(this.lexer.yytext);
        lstack.push(this.lexer.yylloc);
        stack.push(action[1]);
        symbol = null;
        if (!preErrorSymbol) {
            yyleng = this.lexer.yyleng;
            yytext = this.lexer.yytext;
            yylineno = this.lexer.yylineno;
            yyloc = this.lexer.yylloc;
            if (recovering > 0)
                recovering--;
        } else {
            symbol = preErrorSymbol;
            preErrorSymbol = null;
        }
        break;
    case 2:
        len = this.productions_[action[1]][1];
        yyval.$ = vstack[vstack.length - len];
        yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column};
        if (ranges) {
            yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
        }
        r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
        if (typeof r !== "undefined") {
            return r;
        }
        if (len) {
            stack = stack.slice(0, -1 * len * 2);
            vstack = vstack.slice(0, -1 * len);
            lstack = lstack.slice(0, -1 * len);
        }
        stack.push(this.productions_[action[1]][0]);
        vstack.push(yyval.$);
        lstack.push(yyval._$);
        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
        stack.push(newState);
        break;
    case 3:
        return true;
    }
}
return true;

} }; ;function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; return new Parser; })(); if (typeof require !== ‘undefined’ && typeof exports !== ‘undefined’) { exports.parser = parser; exports.Parser = parser.Parser; exports.parse = function () { return parser.parse.apply(parser, arguments); } exports.main = function commonjsMain(args) {

if (!args[1])
    throw new Error('Usage: '+args[0]+' FILE');
var source, cwd;
if (typeof process !== 'undefined') {
    source = require('fs').readFileSync(require('path').resolve(args[1]), "utf8");
} else {
    source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
}
return exports.parser.parse(source);

} if (typeof module !== ‘undefined’ && require.main === module) {

exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);

} }var AssociationCollection, COMMENT, Cache, Collection, Compile, DynamicNode, Event, IDENTIFIER, KEYWORDS, LITERAL, Lexer, MULTI_DENT, Map, Model, Node, Property, PropertyAccessor, PropertyDefinition, STRING, Serenade, Transform, View, WHITESPACE, assignUnlessEqual, capitalize, compile, def, defineEvent, defineOptions, defineProperty, extend, format, getValue, hash, idCounter, isArray, isArrayIndex, merge, normalize, pairToObject, primitiveTypes, safeDelete, safePush, serializeObject, settings,

__hasProp = {}.hasOwnProperty,
__slice = [].slice,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

settings = {

async: false

};

def = Object.defineProperty;

primitiveTypes = [“undefined”, “boolean”, “number”, “string”];

defineOptions = function(object, name) {

return def(object, name, {
  get: function() {
    var options;

    if (!this.hasOwnProperty("_" + name)) {
      options = name in Object.getPrototypeOf(this) ? Object.create(Object.getPrototypeOf(this)[name]) : {};
      def(this, "_" + name, {
        configurable: true,
        writable: true,
        value: options
      });
    }
    return this["_" + name];
  }
});

};

extend = function(target, source, enumerable) {

var key, value;

if (enumerable == null) {
  enumerable = true;
}
for (key in source) {
  if (!__hasProp.call(source, key)) continue;
  value = source[key];
  if (enumerable) {
    target[key] = value;
  } else {
    def(target, key, {
      value: value,
      configurable: true
    });
  }
}
return target;

};

assignUnlessEqual = function(object, prop, value) {

if (object[prop] !== value) {
  return object[prop] = value;
}

};

merge = function(target, source, enumerable) {

if (enumerable == null) {
  enumerable = true;
}
return extend(extend({}, target, enumerable), source, enumerable);

};

format = function(model, key) {

if (model[key + "_property"]) {
  return model[key + "_property"].format();
} else {
  return model[key];
}

};

isArray = function(object) {

return Object.prototype.toString.call(object) === "[object Array]";

};

pairToObject = function(one, two) {

var temp;

temp = {};
temp[one] = two;
return temp;

};

serializeObject = function(object) {

var item, _i, _len, _results;

if (object && typeof object.toJSON === 'function') {
  return object.toJSON();
} else if (isArray(object)) {
  _results = [];
  for (_i = 0, _len = object.length; _i < _len; _i++) {
    item = object[_i];
    _results.push(serializeObject(item));
  }
  return _results;
} else {
  return object;
}

};

capitalize = function(word) {

return word.slice(0, 1).toUpperCase() + word.slice(1);

};

hash = function(value) {

var key;

key = value instanceof Object ? (!("_s_hash" in value) ? def(value, "_s_hash", {
  value: ++arguments.callee.current
}) : void 0, value._s_hash) : value;
return (typeof value) + ' ' + key;

};

hash.current = 0;

safePush = function(object, collection, item) {

if (!object[collection] || object[collection].indexOf(item) === -1) {
  if (object.hasOwnProperty(collection)) {
    return object[collection].push(item);
  } else if (object[collection]) {
    return def(object, collection, {
      value: [item].concat(object[collection])
    });
  } else {
    return def(object, collection, {
      value: [item]
    });
  }
}

};

safeDelete = function(object, collection, item) {

var index;

if (object[collection] && (index = object[collection].indexOf(item)) !== -1) {
  if (!object.hasOwnProperty(collection)) {
    def(object, collection, {
      value: [].concat(object[collection])
    });
  }
  return object[collection].splice(index, 1);
}

};

Map = (function() {

function Map(array) {
  var element, index, _i, _len;

  this.map = {};
  for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
    element = array[index];
    this.put(index, element);
  }
}

Map.prototype.isMember = function(element) {
  var _ref;

  return ((_ref = this.map[hash(element)]) != null ? _ref[0].length : void 0) > 0;
};

Map.prototype.indexOf = function(element) {
  var _ref, _ref1;

  return (_ref = this.map[hash(element)]) != null ? (_ref1 = _ref[0]) != null ? _ref1[0] : void 0 : void 0;
};

Map.prototype.put = function(index, element) {
  var existing;

  existing = this.map[hash(element)];
  return this.map[hash(element)] = existing ? [
    existing[0].concat(index).sort(function(a, b) {
      return a - b;
    }), element
  ] : [[index], element];
};

Map.prototype.remove = function(element) {
  var _base, _ref;

  return (_ref = this.map[hash(element)]) != null ? typeof (_base = _ref[0]).shift === "function" ? _base.shift() : void 0 : void 0;
};

return Map;

})();

Transform = function(from, to) {

var actual, cleaned, cleanedMap, complete, completeMap, element, index, indexActual, indexWanted, operations, targetMap, wanted, _i, _j, _k, _len, _len1, _len2;

if (from == null) {
  from = [];
}
if (to == null) {
  to = [];
}
operations = [];
to = to.map(function(e) {
  return e;
});
targetMap = new Map(to);
cleaned = [];
for (_i = 0, _len = from.length; _i < _len; _i++) {
  element = from[_i];
  if (targetMap.isMember(element)) {
    cleaned.push(element);
  } else {
    operations.push({
      type: "remove",
      index: cleaned.length
    });
  }
  targetMap.remove(element);
}
complete = [].concat(cleaned);
cleanedMap = new Map(cleaned);
for (index = _j = 0, _len1 = to.length; _j < _len1; index = ++_j) {
  element = to[index];
  if (!cleanedMap.isMember(element)) {
    operations.push({
      type: "insert",
      index: index,
      value: element
    });
    complete.splice(index, 0, element);
  }
  cleanedMap.remove(element);
}
completeMap = new Map(complete);
for (indexActual = _k = 0, _len2 = complete.length; _k < _len2; indexActual = ++_k) {
  actual = complete[indexActual];
  wanted = to[indexActual];
  if (actual !== wanted) {
    indexWanted = completeMap.indexOf(wanted);
    completeMap.remove(actual);
    completeMap.remove(wanted);
    completeMap.put(indexWanted, actual);
    complete[indexActual] = wanted;
    complete[indexWanted] = actual;
    operations.push({
      type: "swap",
      index: indexActual,
      "with": indexWanted
    });
  } else {
    completeMap.remove(actual);
  }
}
return operations;

};

Event = (function() {

function Event(object, name, options) {
  this.object = object;
  this.name = name;
  this.options = options;
}

def(Event.prototype, "async", {
  get: function() {
    if ("async" in this.options) {
      return this.options.async;
    } else {
      return settings.async;
    }
  }
});

Event.prototype.trigger = function() {
  var args, _base,
    _this = this;

  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  if (this.listeners.length) {
    this.queue.push(args);
    if (this.async) {
      if (this.options.animate) {
        return (_base = this.queue).frame || (_base.frame = requestAnimationFrame((function() {
          return _this.resolve();
        }), this.options.timeout || 0));
      } else {
        if (this.queue.timeout && !this.options.buffer) {
          return;
        }
        clearTimeout(this.queue.timeout);
        return this.queue.timeout = setTimeout((function() {
          return _this.resolve();
        }), this.options.timeout || 0);
      }
    } else {
      return this.resolve();
    }
  }
};

Event.prototype.bind = function(fun) {
  if (this.options.bind) {
    this.options.bind.call(this.object, fun);
  }
  return safePush(this.object._s, "listeners_" + this.name, fun);
};

Event.prototype.one = function(fun) {
  var unbind,
    _this = this;

  unbind = function(fun) {
    return _this.unbind(fun);
  };
  return this.bind(function() {
    unbind(arguments.callee);
    return fun.apply(this, arguments);
  });
};

Event.prototype.unbind = function(fun) {
  safeDelete(this.object._s, "listeners_" + this.name, fun);
  if (this.options.unbind) {
    return this.options.unbind.call(this.object, fun);
  }
};

Event.prototype.resolve = function() {
  var args, perform, _i, _len, _ref,
    _this = this;

  if (this.queue.frame) {
    cancelAnimationFrame(this.queue.frame);
  }
  clearTimeout(this.queue.timeout);
  if (this.queue.length) {
    perform = function(args) {
      if (_this.listeners) {
        return ([].concat(_this.listeners)).forEach(function(listener) {
          return listener.apply(_this.object, args);
        });
      }
    };
    if (this.options.optimize) {
      perform(this.options.optimize(this.queue));
    } else {
      _ref = this.queue;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        args = _ref[_i];
        perform(args);
      }
    }
  }
  return this.queue = [];
};

def(Event.prototype, "listeners", {
  get: function() {
    return this.object._s["listeners_" + this.name] || [];
  }
});

def(Event.prototype, "queue", {
  get: function() {
    if (!this.object._s.hasOwnProperty("queue_" + this.name)) {
      this.queue = [];
    }
    return this.object._s["queue_" + this.name];
  },
  set: function(val) {
    return this.object._s["queue_" + this.name] = val;
  }
});

return Event;

})();

defineEvent = function(object, name, options) {

if (options == null) {
  options = {};
}
if (!("_s" in object)) {
  defineOptions(object, "_s");
}
return def(object, name, {
  configurable: true,
  get: function() {
    return new Event(this, name, options);
  }
});

};

Cache = {

_identityMap: {},
get: function(ctor, id) {
  var name, _ref;

  name = ctor.uniqueId();
  if (name && id) {
    return (_ref = this._identityMap[name]) != null ? _ref[id] : void 0;
  }
},
set: function(ctor, id, obj) {
  var name, _base;

  name = ctor.uniqueId();
  if (name && id) {
    (_base = this._identityMap)[name] || (_base[name] = {});
    return this._identityMap[name][id] = obj;
  }
},
unset: function(ctor, id) {
  var name, _base;

  name = ctor.uniqueId();
  if (name && id) {
    (_base = this._identityMap)[name] || (_base[name] = {});
    return delete this._identityMap[name][id];
  }
}

};

isArrayIndex = function(index) {

return ("" + index).match(/^\d+$/);

};

Collection = (function() {

var _this = this;

defineEvent(Collection.prototype, "change");

def(Collection.prototype, "first", {
  get: function() {
    return this[0];
  }
});

def(Collection.prototype, "last", {
  get: function() {
    return this[this.length - 1];
  }
});

function Collection(list) {
  var index, val, _i, _len;

  if (list == null) {
    list = [];
  }
  for (index = _i = 0, _len = list.length; _i < _len; index = ++_i) {
    val = list[index];
    this[index] = val;
  }
  this.length = (list != null ? list.length : void 0) || 0;
}

Collection.prototype.get = function(index) {
  return this[index];
};

Collection.prototype.set = function(index, value) {
  this[index] = value;
  if (isArrayIndex(index)) {
    this.length = Math.max(this.length, index + 1);
  }
  return value;
};

Collection.prototype.update = function(list) {
  var index, val, _, _i, _len;

  for (index in this) {
    _ = this[index];
    if (isArrayIndex(index)) {
      delete this[index];
    }
  }
  for (index = _i = 0, _len = list.length; _i < _len; index = ++_i) {
    val = list[index];
    this[index] = val;
  }
  this.length = (list != null ? list.length : void 0) || 0;
  return list;
};

Collection.prototype.sortBy = function(attribute) {
  return this.sort(function(a, b) {
    if (a[attribute] < b[attribute]) {
      return -1;
    } else {
      return 1;
    }
  });
};

Collection.prototype.includes = function(item) {
  return this.indexOf(item) >= 0;
};

Collection.prototype.find = function(fun) {
  var item, _i, _len;

  for (_i = 0, _len = this.length; _i < _len; _i++) {
    item = this[_i];
    if (fun(item)) {
      return item;
    }
  }
};

Collection.prototype.insertAt = function(index, value) {
  Array.prototype.splice.call(this, index, 0, value);
  return value;
};

Collection.prototype.deleteAt = function(index) {
  var value;

  value = this[index];
  Array.prototype.splice.call(this, index, 1);
  return value;
};

Collection.prototype["delete"] = function(item) {
  var index;

  index = this.indexOf(item);
  if (index !== -1) {
    return this.deleteAt(index);
  }
};

Collection.prototype.concat = function() {
  var arg, args, _ref;

  args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  args = (function() {
    var _i, _len, _results;

    _results = [];
    for (_i = 0, _len = args.length; _i < _len; _i++) {
      arg = args[_i];
      if (arg instanceof Collection) {
        _results.push(arg.toArray());
      } else {
        _results.push(arg);
      }
    }
    return _results;
  })();
  return new Collection((_ref = this.toArray()).concat.apply(_ref, args));
};

Collection.prototype.toArray = function() {
  var array, index, val;

  array = [];
  for (index in this) {
    val = this[index];
    if (isArrayIndex(index)) {
      array[index] = val;
    }
  }
  return array;
};

Collection.prototype.clone = function() {
  return new Collection(this.toArray());
};

Collection.prototype.toString = function() {
  return this.toArray().toString();
};

Collection.prototype.toLocaleString = function() {
  return this.toArray().toLocaleString();
};

Collection.prototype.toJSON = function() {
  return serializeObject(this.toArray());
};

Object.getOwnPropertyNames(Array.prototype).forEach(function(fun) {
  var _base;

  return (_base = Collection.prototype)[fun] || (_base[fun] = Array.prototype[fun]);
});

["splice", "map", "filter", "slice"].forEach(function(fun) {
  var original;

  original = Collection.prototype[fun];
  return Collection.prototype[fun] = function() {
    return new Collection(original.apply(this, arguments));
  };
});

["push", "pop", "unshift", "shift", "splice", "sort", "reverse", "update", "set", "insertAt", "deleteAt"].forEach(function(fun) {
  var original;

  original = Collection.prototype[fun];
  return Collection.prototype[fun] = function() {
    var old, val;

    old = this.clone();
    val = original.apply(this, arguments);
    this.change.trigger(old, this);
    return val;
  };
});

return Collection;

}).call(this);

AssociationCollection = (function(_super) {

__extends(AssociationCollection, _super);

function AssociationCollection(owner, options, list) {
  var _this = this;

  this.owner = owner;
  this.options = options;
  this._convert.apply(this, __slice.call(list).concat([function() {
    var items;

    items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    return AssociationCollection.__super__.constructor.call(_this, items);
  }]));
}

AssociationCollection.prototype.set = function(index, item) {
  var _this = this;

  return this._convert(item, function(item) {
    return AssociationCollection.__super__.set.call(_this, index, item);
  });
};

AssociationCollection.prototype.push = function(item) {
  var _this = this;

  return this._convert(item, function(item) {
    return AssociationCollection.__super__.push.call(_this, item);
  });
};

AssociationCollection.prototype.update = function(list) {
  var _this = this;

  return this._convert.apply(this, __slice.call(list).concat([function() {
    var items;

    items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    return AssociationCollection.__super__.update.call(_this, items);
  }]));
};

AssociationCollection.prototype.splice = function() {
  var deleteCount, list, start,
    _this = this;

  start = arguments[0], deleteCount = arguments[1], list = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
  return this._convert.apply(this, __slice.call(list).concat([function() {
    var items;

    items = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    return AssociationCollection.__super__.splice.apply(_this, [start, deleteCount].concat(__slice.call(items)));
  }]));
};

AssociationCollection.prototype.insertAt = function(index, item) {
  var _this = this;

  return this._convert(item, function(item) {
    return AssociationCollection.__super__.insertAt.call(_this, index, item);
  });
};

AssociationCollection.prototype._convert = function() {
  var fn, item, items, returnValue, _i, _j, _len;

  items = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), fn = arguments[_i++];
  items = (function() {
    var _j, _len, _results;

    _results = [];
    for (_j = 0, _len = items.length; _j < _len; _j++) {
      item = items[_j];
      if ((item != null ? item.constructor : void 0) === Object && this.options.as) {
        _results.push(item = new (this.options.as())(item));
      } else {
        _results.push(item);
      }
    }
    return _results;
  }).call(this);
  returnValue = fn.apply(null, items);
  for (_j = 0, _len = items.length; _j < _len; _j++) {
    item = items[_j];
    if (this.options.inverseOf && item[this.options.inverseOf] !== this.owner) {
      item[this.options.inverseOf] = this.owner;
    }
  }
  return returnValue;
};

return AssociationCollection;

})(Collection);

PropertyDefinition = (function() {

function PropertyDefinition(name, options) {
  var _i, _len, _ref;

  this.name = name;
  extend(this, options);
  this.dependencies = [];
  this.localDependencies = [];
  this.globalDependencies = [];
  if (this.dependsOn) {
    _ref = [].concat(this.dependsOn);
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      name = _ref[_i];
      this.addDependency(name);
    }
  }
}

def(PropertyDefinition.prototype, "eventOptions", {
  get: function() {
    var name, options;

    name = this.name;
    options = {
      timeout: this.timeout,
      buffer: this.buffer,
      animate: this.animate,
      bind: function() {
        this[name];
        return this[name + "_property"].registerGlobal();
      },
      optimize: function(queue) {
        var _ref, _ref1;

        return [(_ref = queue[0]) != null ? _ref[0] : void 0, (_ref1 = queue[queue.length - 1]) != null ? _ref1[1] : void 0];
      }
    };
    if (this.async != null) {
      options.async = this.async;
    }
    return options;
  }
});

PropertyDefinition.prototype.addDependency = function(name) {
  var subname, type, _ref, _ref1;

  if (this.dependencies.indexOf(name) === -1) {
    this.dependencies.push(name);
    if (name.match(/\./)) {
      type = "singular";
      _ref = name.split("."), name = _ref[0], subname = _ref[1];
    } else if (name.match(/:/)) {
      type = "collection";
      _ref1 = name.split(":"), name = _ref1[0], subname = _ref1[1];
    }
    this.localDependencies.push(name);
    if (this.localDependencies.indexOf(name) === -1) {
      this.localDependencies.push(name);
    }
    if (type) {
      return this.globalDependencies.push({
        subname: subname,
        name: name,
        type: type
      });
    }
  }
};

return PropertyDefinition;

})();

PropertyAccessor = (function() {

var _this = this;

function PropertyAccessor(definition, object) {
  this.definition = definition;
  this.object = object;
  this.trigger = __bind(this.trigger, this);
  this.name = this.definition.name;
  this.valueName = "_" + this.name;
  this.event = new Event(this.object, this.name + "_change", this.definition.eventOptions);
  this._gcQueue = [];
}

PropertyAccessor.prototype.set = function(value) {
  if (typeof value === "function") {
    return this.definition.get = value;
  } else {
    if (this.definition.set) {
      this.definition.set.call(this.object, value);
    } else {
      def(this.object, this.valueName, {
        value: value,
        configurable: true
      });
    }
    return this.trigger();
  }
};

PropertyAccessor.prototype.get = function() {
  var listener, value,
    _this = this;

  if (this.definition.get && !(this.definition.cache && this.valueName in this.object)) {
    listener = function(name) {
      return _this.definition.addDependency(name);
    };
    if (!("dependsOn" in this.definition)) {
      this.object._s.property_access.bind(listener);
    }
    value = this.definition.get.call(this.object);
    if (!("dependsOn" in this.definition)) {
      this.object._s.property_access.unbind(listener);
    }
    if (this.definition.cache) {
      this.object[this.valueName] = value;
      if (!this._isCached) {
        this._isCached = true;
        this.bind(function() {});
      }
    }
  } else {
    value = this.object[this.valueName];
  }
  this.object._s.property_access.trigger(this.name);
  return value;
};

PropertyAccessor.prototype.format = function() {
  if (typeof this.definition.format === "function") {
    return this.definition.format.call(this.object, this.get());
  } else {
    return this.get();
  }
};

PropertyAccessor.prototype.registerGlobal = function() {
  var dependency, _i, _len, _ref, _ref1, _results,
    _this = this;

  if (this._isRegistered) {
    return;
  }
  this._isRegistered = true;
  this.definition.globalDependencies.forEach(function(dep) {
    var name, subname, type, updateCollectionBindings, updateItemBinding, updateItemBindings, _ref, _ref1;

    name = dep.name, type = dep.type, subname = dep.subname;
    switch (type) {
      case "singular":
        updateItemBinding = function(before, after) {
          var _ref, _ref1;

          if (before != null) {
            if ((_ref = before[subname + "_property"]) != null) {
              _ref.unbind(_this.trigger);
            }
          }
          return after != null ? (_ref1 = after[subname + "_property"]) != null ? _ref1.bind(_this.trigger) : void 0 : void 0;
        };
        if ((_ref = _this.object[name + "_property"]) != null) {
          _ref.bind(updateItemBinding);
        }
        updateItemBinding(void 0, _this.object[name]);
        return _this._gcQueue.push(function() {
          var _ref1;

          updateItemBinding(_this.object[name], void 0);
          return (_ref1 = _this.object[name + "_property"]) != null ? _ref1.unbind(updateItemBinding) : void 0;
        });
      case "collection":
        updateItemBindings = function(before, after) {
          if (before != null) {
            if (typeof before.forEach === "function") {
              before.forEach(function(item) {
                var _ref1;

                return (_ref1 = item[subname + "_property"]) != null ? _ref1.unbind(_this.trigger) : void 0;
              });
            }
          }
          return after != null ? typeof after.forEach === "function" ? after.forEach(function(item) {
            var _ref1;

            return (_ref1 = item[subname + "_property"]) != null ? _ref1.bind(_this.trigger) : void 0;
          }) : void 0 : void 0;
        };
        updateCollectionBindings = function(before, after) {
          var _ref1, _ref2, _ref3, _ref4;

          updateItemBindings(before, after);
          if (before != null) {
            if ((_ref1 = before.change) != null) {
              _ref1.unbind(_this.trigger);
            }
          }
          if (after != null) {
            if ((_ref2 = after.change) != null) {
              _ref2.bind(_this.trigger);
            }
          }
          if (before != null) {
            if ((_ref3 = before.change) != null) {
              _ref3.unbind(updateItemBindings);
            }
          }
          return after != null ? (_ref4 = after.change) != null ? _ref4.bind(updateItemBindings) : void 0 : void 0;
        };
        if ((_ref1 = _this.object[name + "_property"]) != null) {
          _ref1.bind(updateCollectionBindings);
        }
        updateCollectionBindings(void 0, _this.object[name]);
        return _this._gcQueue.push(function() {
          var _ref2;

          updateCollectionBindings(_this.object[name], void 0);
          return (_ref2 = _this.object[name + "_property"]) != null ? _ref2.unbind(updateCollectionBindings) : void 0;
        });
    }
  });
  _ref = this.definition.localDependencies;
  _results = [];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    dependency = _ref[_i];
    _results.push((_ref1 = this.object[dependency + "_property"]) != null ? _ref1.registerGlobal() : void 0);
  }
  return _results;
};

PropertyAccessor.prototype.gc = function() {
  var dependency, fn, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results,
    _this = this;

  if (this.listeners.length === 0 && !this.dependentProperties.find(function(prop) {
    return prop.listeners.length !== 0;
  })) {
    _ref = this._gcQueue;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      fn = _ref[_i];
      fn();
    }
    this._isRegistered = false;
  }
  _ref1 = this.definition.localDependencies;
  _results = [];
  for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
    dependency = _ref1[_j];
    _results.push((_ref2 = this.object[dependency + "_property"]) != null ? _ref2.gc() : void 0);
  }
  return _results;
};

PropertyAccessor.prototype.trigger = function() {
  var changes, name, newValue, _i, _len, _ref, _ref1;

  this.clearCache();
  if (this.hasChanged()) {
    newValue = this.get();
    this.event.trigger(this._oldValue, newValue);
    changes = {};
    changes[this.name] = newValue;
    if ((_ref = this.object.changed) != null) {
      if (typeof _ref.trigger === "function") {
        _ref.trigger(changes);
      }
    }
    _ref1 = this.dependents;
    for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
      name = _ref1[_i];
      this.object[name + "_property"].trigger();
    }
    return this._oldValue = newValue;
  }
};

["bind", "one", "resolve"].forEach(function(fn) {
  return PropertyAccessor.prototype[fn] = function() {
    var _ref;

    return (_ref = this.event)[fn].apply(_ref, arguments);
  };
});

PropertyAccessor.prototype.unbind = function(fn) {
  this.event.unbind(fn);
  return this.gc();
};

def(PropertyAccessor.prototype, "dependents", {
  get: function() {
    var deps, findDependencies,
      _this = this;

    deps = [];
    findDependencies = function(name) {
      var property, _i, _len, _ref, _ref1, _results;

      _ref = _this.object._s.properties;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        property = _ref[_i];
        if ((_ref1 = property.name, __indexOf.call(deps, _ref1) < 0) && __indexOf.call(property.localDependencies, name) >= 0) {
          deps.push(property.name);
          _results.push(findDependencies(property.name));
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };
    findDependencies(this.name);
    return deps;
  }
});

def(PropertyAccessor.prototype, "listeners", {
  get: function() {
    return this.event.listeners;
  }
});

PropertyAccessor.prototype.clearCache = function() {
  if (this.definition.cache && this.definition.get) {
    return delete this.object[this.valueName];
  }
};

PropertyAccessor.prototype.hasChanged = function() {
  var _ref, _ref1;

  if ((_ref = this.definition.changed) === true || _ref === false) {
    return this.definition.changed;
  } else {
    if ("_oldValue" in this) {
      if (this.definition.changed) {
        return this.definition.changed.call(this.object, this._oldValue, this.get());
      } else {
        if (_ref1 = typeof this._oldValue, __indexOf.call(primitiveTypes, _ref1) >= 0) {
          return this._oldValue !== this.get();
        } else {
          return true;
        }
      }
    } else {
      return true;
    }
  }
};

def(PropertyAccessor.prototype, "dependentProperties", {
  get: function() {
    var name;

    return new Serenade.Collection((function() {
      var _i, _len, _ref, _results;

      _ref = this.dependents;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        name = _ref[_i];
        _results.push(this.object[name + "_property"]);
      }
      return _results;
    }).call(this));
  }
});

return PropertyAccessor;

}).call(this);

defineProperty = function(object, name, options) {

var accessorName, definition;

if (options == null) {
  options = {};
}
definition = new PropertyDefinition(name, options);
if (!("_s" in object)) {
  defineOptions(object, "_s");
}
safePush(object._s, "properties", definition);
defineEvent(object._s, "property_access");
def(object, name, {
  get: function() {
    return this[name + "_property"].get();
  },
  set: function(value) {
    return this[name + "_property"].set(value);
  },
  configurable: true,
  enumerable: "enumerable" in options ? options.enumerable : true
});
accessorName = name + "_property";
def(object, accessorName, {
  get: function() {
    if (!this._s.hasOwnProperty(accessorName)) {
      this._s[accessorName] = new PropertyAccessor(definition, this);
    }
    return this._s[accessorName];
  },
  configurable: true
});
if (typeof options.serialize === 'string') {
  defineProperty(object, options.serialize, {
    get: function() {
      return this[name];
    },
    set: function(v) {
      return this[name] = v;
    },
    configurable: true
  });
}
if ("value" in options) {
  return object[name] = options.value;
}

};

idCounter = 1;

Model = (function() {

Model.identityMap = true;

Model.find = function(id) {
  return Cache.get(this, id) || new this({
    id: id
  });
};

Model.extend = function(ctor) {
  var New;

  return New = (function(_super) {
    __extends(New, _super);

    function New() {
      var val;

      val = New.__super__.constructor.apply(this, arguments);
      if (val) {
        return val;
      }
      if (ctor) {
        ctor.apply(this, arguments);
      }
    }

    return New;

  })(this);
};

Model.property = function() {
  var name, names, options, _i, _j, _len, _results;

  names = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
  if (typeof options === "string") {
    names.push(options);
    options = {};
  }
  _results = [];
  for (_j = 0, _len = names.length; _j < _len; _j++) {
    name = names[_j];
    _results.push(defineProperty(this.prototype, name, options));
  }
  return _results;
};

Model.event = function(name, options) {
  return defineEvent(this.prototype, name, options);
};

Model.delegate = function() {
  var names, options, to, _i,
    _this = this;

  names = 2 <= arguments.length ? __slice.call(arguments, 0, _i = arguments.length - 1) : (_i = 0, []), options = arguments[_i++];
  to = options.to;
  return names.forEach(function(name) {
    var propName, propOptions;

    propName = name;
    if (options.prefix === true) {
      propName = to + capitalize(name);
    } else if (options.prefix) {
      propName = options.prefix + capitalize(name);
    }
    if (options.suffix === true) {
      propName = propName + capitalize(to);
    } else if (options.suffix) {
      propName = propName + options.suffix;
    }
    propOptions = merge(options, {
      dependsOn: options.dependsOn || ("" + to + "." + name),
      get: function() {
        var _ref;

        return (_ref = this[to]) != null ? _ref[name] : void 0;
      },
      set: function(value) {
        var _ref;

        return (_ref = this[to]) != null ? _ref[name] = value : void 0;
      },
      format: function() {
        if (this[to] != null) {
          return Serenade.format(this[to], name);
        }
      }
    });
    return _this.property(propName, propOptions);
  });
};

Model.collection = function(name, options) {
  var propOptions;

  if (options == null) {
    options = {};
  }
  propOptions = merge(options, {
    changed: true,
    get: function() {
      var valueName;

      valueName = "_" + name;
      if (!this[valueName]) {
        this[valueName] = new Collection([]);
        this[valueName].change.bind(this[name + "_property"].trigger);
      }
      return this[valueName];
    },
    set: function(value) {
      return this[name].update(value);
    }
  });
  this.property(name, propOptions);
  return this.property(name + 'Count', {
    get: function() {
      return this[name].length;
    },
    dependsOn: name
  });
};

Model.belongsTo = function(name, options) {
  var propOptions;

  if (options == null) {
    options = {};
  }
  propOptions = merge(options, {
    set: function(model) {
      var previous, valueName;

      valueName = "_" + name;
      if (model && model.constructor === Object && options.as) {
        model = new (options.as())(model);
      }
      previous = this[valueName];
      this[valueName] = model;
      if (options.inverseOf && !model[options.inverseOf].includes(this)) {
        if (previous) {
          previous[options.inverseOf]["delete"](this);
        }
        return model[options.inverseOf].push(this);
      }
    }
  });
  this.property(name, propOptions);
  return this.property(name + 'Id', {
    get: function() {
      var _ref;

      return (_ref = this[name]) != null ? _ref.id : void 0;
    },
    set: function(id) {
      if (id != null) {
        return this[name] = options.as().find(id);
      }
    },
    dependsOn: name,
    serialize: options.serializeId
  });
};

Model.hasMany = function(name, options) {
  var propOptions;

  if (options == null) {
    options = {};
  }
  propOptions = merge(options, {
    changed: true,
    get: function() {
      var valueName;

      valueName = "_" + name;
      if (!this[valueName]) {
        this[valueName] = new AssociationCollection(this, options, []);
        this[valueName].change.bind(this[name + "_property"].trigger);
      }
      return this[valueName];
    },
    set: function(value) {
      return this[name].update(value);
    }
  });
  this.property(name, propOptions);
  this.property(name + 'Ids', {
    get: function() {
      return new Collection(this[name]).map(function(item) {
        return item != null ? item.id : void 0;
      });
    },
    set: function(ids) {
      var id, objects;

      objects = (function() {
        var _i, _len, _results;

        _results = [];
        for (_i = 0, _len = ids.length; _i < _len; _i++) {
          id = ids[_i];
          _results.push(options.as().find(id));
        }
        return _results;
      })();
      return this[name].update(objects);
    },
    dependsOn: name,
    serialize: options.serializeIds
  });
  return this.property(name + 'Count', {
    get: function() {
      return this[name].length;
    },
    dependsOn: name
  });
};

Model.selection = function(name, options) {
  var propOptions;

  if (options == null) {
    options = {};
  }
  propOptions = merge(options, {
    get: function() {
      return this[options.from].filter(function(item) {
        return item[options.filter];
      });
    },
    dependsOn: "" + options.from + ":" + options.filter
  });
  this.property(name, propOptions);
  return this.property(name + 'Count', {
    get: function() {
      return this[name].length;
    },
    dependsOn: name
  });
};

Model.uniqueId = function() {
  if (!(this._uniqueId && this._uniqueGen === this)) {
    this._uniqueId = (idCounter += 1);
    this._uniqueGen = this;
  }
  return this._uniqueId;
};

Model.property('id', {
  serialize: true,
  set: function(val) {
    Cache.unset(this.constructor, this.id);
    Cache.set(this.constructor, val, this);
    return this._s.val_id = val;
  },
  get: function() {
    return this._s.val_id;
  }
});

Model.event("saved");

Model.event("changed", {
  optimize: function(queue) {
    var item, result, _i, _len;

    result = {};
    for (_i = 0, _len = queue.length; _i < _len; _i++) {
      item = queue[_i];
      extend(result, item[0]);
    }
    return [result];
  }
});

function Model(attributes) {
  var fromCache;

  if (this.constructor.identityMap && (attributes != null ? attributes.id : void 0)) {
    fromCache = Cache.get(this.constructor, attributes.id);
    if (fromCache) {
      fromCache.set(attributes);
      return fromCache;
    } else {
      Cache.set(this.constructor, attributes.id, this);
    }
  }
  this.set(attributes);
}

Model.prototype.set = function(attributes) {
  var name, value, _results;

  _results = [];
  for (name in attributes) {
    if (!__hasProp.call(attributes, name)) continue;
    value = attributes[name];
    if (!(name in this)) {
      defineProperty(this, name);
    }
    _results.push(this[name] = value);
  }
  return _results;
};

Model.prototype.save = function() {
  return this.saved.trigger();
};

Model.prototype.toJSON = function() {
  var key, property, serialized, value, _i, _len, _ref, _ref1;

  serialized = {};
  _ref = this._s.properties;
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    property = _ref[_i];
    if (typeof property.serialize === 'string') {
      serialized[property.serialize] = serializeObject(this[property.name]);
    } else if (typeof property.serialize === 'function') {
      _ref1 = property.serialize.call(this), key = _ref1[0], value = _ref1[1];
      serialized[key] = serializeObject(value);
    } else if (property.serialize) {
      serialized[property.name] = serializeObject(this[property.name]);
    }
  }
  return serialized;
};

Model.prototype.toString = function() {
  return JSON.stringify(this.toJSON());
};

return Model;

})();

IDENTIFIER = /^[a-zA-Z]*/;

LITERAL = /^[[]=:-!#.@]/;

STRING = /^“((?:\.|[^”])*)“/;

MULTI_DENT = /^(?:r?n*)+/;

WHITESPACE = /^[^rnS]+/;

COMMENT = /^s*//*/;

KEYWORDS = [“IF”, “ELSE”, “COLLECTION”, “IN”, “VIEW”, “UNLESS”];

Lexer = (function() {

function Lexer() {}

Lexer.prototype.tokenize = function(code, opts) {
  var tag;

  if (opts == null) {
    opts = {};
  }
  this.code = code.replace(/^\s*/, '').replace(/\s*$/, '');
  this.line = opts.line || 0;
  this.indent = 0;
  this.indents = [];
  this.ends = [];
  this.tokens = [];
  this.i = 0;
  while (this.chunk = this.code.slice(this.i)) {
    this.i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.stringToken() || this.literalToken();
  }
  while (tag = this.ends.pop()) {
    if (tag === 'OUTDENT') {
      this.token('OUTDENT');
    } else {
      this.error("missing " + tag);
    }
  }
  while (this.tokens[0][0] === "TERMINATOR") {
    this.tokens.shift();
  }
  while (this.tokens[this.tokens.length - 1][0] === "TERMINATOR") {
    this.tokens.pop();
  }
  return this.tokens;
};

Lexer.prototype.commentToken = function() {
  var match;

  if (match = COMMENT.exec(this.chunk)) {
    return match[0].length;
  } else {
    return 0;
  }
};

Lexer.prototype.whitespaceToken = function() {
  var match;

  if (match = WHITESPACE.exec(this.chunk)) {
    this.token('WHITESPACE', match[0].length);
    return match[0].length;
  } else {
    return 0;
  }
};

Lexer.prototype.token = function(tag, value) {
  return this.tokens.push([tag, value, this.line]);
};

Lexer.prototype.identifierToken = function() {
  var match, name;

  if (match = IDENTIFIER.exec(this.chunk)) {
    name = match[0].toUpperCase();
    if (name === "ELSE" && this.last(this.tokens, 2)[0] === "TERMINATOR") {
      this.tokens.splice(this.tokens.length - 3, 1);
    }
    if (__indexOf.call(KEYWORDS, name) >= 0) {
      this.token(name, match[0]);
    } else {
      this.token('IDENTIFIER', match[0]);
    }
    return match[0].length;
  } else {
    return 0;
  }
};

Lexer.prototype.stringToken = function() {
  var match;

  if (match = STRING.exec(this.chunk)) {
    this.token('STRING_LITERAL', match[1]);
    return match[0].length;
  } else {
    return 0;
  }
};

Lexer.prototype.lineToken = function() {
  var diff, indent, match, prev, size;

  if (!(match = MULTI_DENT.exec(this.chunk))) {
    return 0;
  }
  indent = match[0];
  this.line += this.count(indent, '\n');
  prev = this.last(this.tokens, 1);
  size = indent.length - 1 - indent.lastIndexOf('\n');
  diff = size - this.indent;
  if (size === this.indent) {
    this.newlineToken();
  } else if (size > this.indent) {
    this.token('INDENT');
    this.indents.push(diff);
    this.ends.push('OUTDENT');
  } else {
    while (diff < 0) {
      this.ends.pop();
      diff += this.indents.pop();
      this.token('OUTDENT');
    }
    this.token('TERMINATOR', '\n');
  }
  this.indent = size;
  return indent.length;
};

Lexer.prototype.literalToken = function() {
  var match;

  if (match = LITERAL.exec(this.chunk)) {
    this.token(match[0]);
    return 1;
  } else {
    return this.error("Unexpected token '" + (this.chunk.charAt(0)) + "'");
  }
};

Lexer.prototype.newlineToken = function() {
  if (this.tag() !== 'TERMINATOR') {
    return this.token('TERMINATOR', '\n');
  }
};

Lexer.prototype.tag = function(index, tag) {
  var tok;

  return (tok = this.last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
};

Lexer.prototype.value = function(index, val) {
  var tok;

  return (tok = this.last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
};

Lexer.prototype.error = function(message) {
  var chunk;

  chunk = this.code.slice(Math.max(0, this.i - 10), Math.min(this.code.length, this.i + 10));
  throw SyntaxError("" + message + " on line " + (this.line + 1) + " near " + (JSON.stringify(chunk)));
};

Lexer.prototype.count = function(string, substr) {
  var num, pos;

  num = pos = 0;
  if (!substr.length) {
    return 1 / 0;
  }
  while (pos = 1 + string.indexOf(substr, pos)) {
    num++;
  }
  return num;
};

Lexer.prototype.last = function(array, back) {
  return array[array.length - (back || 0) - 1];
};

return Lexer;

})();

Node = (function() {

defineEvent(Node.prototype, "load", {
  async: false
});

defineEvent(Node.prototype, "unload", {
  async: false
});

function Node(ast, element) {
  this.ast = ast;
  this.element = element;
  this.children = new Collection([]);
  this.boundClasses = new Collection([]);
  this.boundEvents = new Collection([]);
}

Node.prototype.append = function(inside) {
  return inside.appendChild(this.element);
};

Node.prototype.insertAfter = function(after) {
  return after.parentNode.insertBefore(this.element, after.nextSibling);
};

Node.prototype.remove = function() {
  var _ref;

  this.detach();
  return (_ref = this.element.parentNode) != null ? _ref.removeChild(this.element) : void 0;
};

def(Node.prototype, "lastElement", {
  configurable: true,
  get: function() {
    return this.element;
  }
});

Node.prototype.nodes = function() {
  return this.children;
};

Node.prototype.bindEvent = function(event, fun) {
  if (event) {
    this.boundEvents.push({
      event: event,
      fun: fun
    });
    return event.bind(fun);
  }
};

Node.prototype.unbindEvent = function(event, fun) {
  if (event) {
    this.boundEvents["delete"](fun);
    return event.unbind(fun);
  }
};

Node.prototype.detach = function() {
  var event, fun, node, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;

  this.unload.trigger();
  _ref = this.nodes();
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    node = _ref[_i];
    node.detach();
  }
  if (this.boundEvents) {
    _ref1 = this.boundEvents;
    _results = [];
    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
      _ref2 = _ref1[_j], event = _ref2.event, fun = _ref2.fun;
      _results.push(event.unbind(fun));
    }
    return _results;
  }
};

Node.prototype.updateClass = function() {
  var classes;

  classes = this.ast.classes;
  if (this.attributeClasses) {
    classes = classes.concat(this.attributeClasses);
  }
  if (this.boundClasses.length) {
    classes = classes.concat(this.boundClasses.toArray());
  }
  classes.sort();
  if (classes.length) {
    return assignUnlessEqual(this.element, "className", classes.join(' '));
  } else {
    return this.element.removeAttribute("class");
  }
};

return Node;

})();

DynamicNode = (function(_super) {

__extends(DynamicNode, _super);

function DynamicNode(ast) {
  this.ast = ast;
  this.anchor = Serenade.document.createTextNode('');
  this.nodeSets = new Collection([]);
  this.boundEvents = new Collection([]);
}

DynamicNode.prototype.nodes = function() {
  var node, nodes, set, _i, _j, _len, _len1, _ref;

  nodes = [];
  _ref = this.nodeSets;
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    set = _ref[_i];
    for (_j = 0, _len1 = set.length; _j < _len1; _j++) {
      node = set[_j];
      nodes.push(node);
    }
  }
  return nodes;
};

DynamicNode.prototype.rebuild = function() {
  var last, node, _i, _len, _ref, _results;

  if (this.anchor.parentNode) {
    last = this.anchor;
    _ref = this.nodes();
    _results = [];
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      node = _ref[_i];
      node.insertAfter(last);
      _results.push(last = node.lastElement);
    }
    return _results;
  }
};

DynamicNode.prototype.replace = function(sets) {
  var set;

  this.clear();
  this.nodeSets.update((function() {
    var _i, _len, _results;

    _results = [];
    for (_i = 0, _len = sets.length; _i < _len; _i++) {
      set = sets[_i];
      _results.push(new Collection(set));
    }
    return _results;
  })());
  return this.rebuild();
};

DynamicNode.prototype.deleteNodeSet = function(index) {
  var node, _i, _len, _ref;

  _ref = this.nodeSets[index];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    node = _ref[_i];
    node.remove();
  }
  return this.nodeSets.deleteAt(index);
};

DynamicNode.prototype.insertNodeSet = function(index, nodes) {
  var last, node, _i, _len, _ref, _ref1;

  last = ((_ref = this.nodeSets[index - 1]) != null ? (_ref1 = _ref.last) != null ? _ref1.lastElement : void 0 : void 0) || this.anchor;
  for (_i = 0, _len = nodes.length; _i < _len; _i++) {
    node = nodes[_i];
    if (this.anchor.parentNode) {
      node.insertAfter(last);
    }
    last = node.lastElement;
  }
  return this.nodeSets.insertAt(index, new Collection(nodes));
};

DynamicNode.prototype.swapNodeSet = function(fromIndex, toIndex) {
  var last, node, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;

  last = ((_ref = this.nodeSets[fromIndex - 1]) != null ? (_ref1 = _ref.last) != null ? _ref1.lastElement : void 0 : void 0) || this.anchor;
  _ref2 = this.nodeSets[toIndex];
  for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
    node = _ref2[_i];
    if (this.anchor.parentNode) {
      node.insertAfter(last);
    }
    last = node.lastElement;
  }
  last = ((_ref3 = this.nodeSets[toIndex - 1]) != null ? (_ref4 = _ref3.last) != null ? _ref4.lastElement : void 0 : void 0) || this.anchor;
  _ref5 = this.nodeSets[fromIndex];
  for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {
    node = _ref5[_j];
    if (this.anchor.parentNode) {
      node.insertAfter(last);
    }
    last = node.lastElement;
  }
  return _ref6 = [this.nodeSets[toIndex], this.nodeSets[fromIndex]], this.nodeSets[fromIndex] = _ref6[0], this.nodeSets[toIndex] = _ref6[1], _ref6;
};

DynamicNode.prototype.clear = function() {
  var node, _i, _len, _ref;

  _ref = this.nodes();
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    node = _ref[_i];
    node.remove();
  }
  return this.nodeSets.update([]);
};

DynamicNode.prototype.remove = function() {
  this.detach();
  this.clear();
  if (this.anchor.parentNode) {
    return this.anchor.parentNode.removeChild(this.anchor);
  }
};

DynamicNode.prototype.append = function(inside) {
  inside.appendChild(this.anchor);
  return this.rebuild();
};

DynamicNode.prototype.insertAfter = function(after) {
  after.parentNode.insertBefore(this.anchor, after.nextSibling);
  return this.rebuild();
};

def(DynamicNode.prototype, "lastElement", {
  configurable: true,
  get: function() {
    var _ref, _ref1;

    return ((_ref = this.nodeSets.last) != null ? (_ref1 = _ref.last) != null ? _ref1.lastElement : void 0 : void 0) || this.anchor;
  }
});

return DynamicNode;

})(Node);

getValue = function(ast, model) {

if (ast.bound && ast.value) {
  return format(model, ast.value);
} else if (ast.value != null) {
  return ast.value;
} else {
  return model;
}

};

Property = {

style: function(ast, node, model, controller) {
  var update;

  update = function() {
    return assignUnlessEqual(node.element.style, ast.name, getValue(ast, model));
  };
  update();
  if (ast.bound) {
    return node.bindEvent(model["" + ast.value + "_property"], update);
  }
},
event: function(ast, node, model, controller) {
  return node.element.addEventListener(ast.name, function(e) {
    if (ast.preventDefault) {
      e.preventDefault();
    }
    return controller[ast.value](node.element, model, e);
  });
},
"class": function(ast, node, model, controller) {
  var update;

  update = function() {
    if (model[ast.value]) {
      if (!node.boundClasses.includes(ast.name)) {
        node.boundClasses.push(ast.name);
      }
    } else {
      node.boundClasses["delete"](ast.name);
    }
    return node.updateClass();
  };
  update();
  return node.bindEvent(model["" + ast.value + "_property"], update);
},
binding: function(ast, node, model, controller) {
  var domUpdated, element, handler, modelUpdated, _ref;

  element = node.element;
  ((_ref = node.ast.name) === "input" || _ref === "textarea" || _ref === "select") || (function() {
    throw SyntaxError("invalid node type " + node.ast.name + " for two way binding");
  })();
  ast.value || (function() {
    throw SyntaxError("cannot bind to whole model, please specify an attribute to bind to");
  })();
  domUpdated = function() {
    return model[ast.value] = element.type === "checkbox" ? element.checked : element.type === "radio" ? element.checked ? element.getAttribute("value") : void 0 : element.value;
  };
  modelUpdated = function() {
    var val;

    val = model[ast.value];
    if (element.type === "checkbox") {
      return element.checked = !!val;
    } else if (element.type === "radio") {
      if (val === element.getAttribute("value")) {
        return element.checked = true;
      }
    } else {
      if (val === void 0) {
        val = "";
      }
      return assignUnlessEqual(element, "value", val);
    }
  };
  modelUpdated();
  node.bindEvent(model["" + ast.value + "_property"], modelUpdated);
  if (ast.name === "binding") {
    handler = function(e) {
      if (element.form === (e.target || e.srcElement)) {
        return domUpdated();
      }
    };
    Serenade.document.addEventListener("submit", handler, true);
    return node.unload.bind(function() {
      return Serenade.document.removeEventListener("submit", handler, true);
    });
  } else {
    return element.addEventListener(ast.name, domUpdated);
  }
},
attribute: function(ast, node, model, controller) {
  var element, update;

  if (ast.name === "binding") {
    return Property.binding(ast, node, model, controller);
  }
  element = node.element;
  update = function() {
    var value;

    value = getValue(ast, model);
    if (ast.name === 'value') {
      return assignUnlessEqual(element, "value", value || '');
    } else if (node.ast.name === 'input' && ast.name === 'checked') {
      return assignUnlessEqual(element, "checked", !!value);
    } else if (ast.name === 'class') {
      node.attributeClasses = value;
      return node.updateClass();
    } else if (value === void 0) {
      if (element.hasAttribute(ast.name)) {
        return element.removeAttribute(ast.name);
      }
    } else {
      if (value === 0) {
        value = "0";
      }
      if (element.getAttribute(ast.name) !== value) {
        return element.setAttribute(ast.name, value);
      }
    }
  };
  if (ast.bound) {
    node.bindEvent(model["" + ast.value + "_property"], update);
  }
  return update();
},
on: function(ast, node, model, controller) {
  var _ref;

  if ((_ref = ast.name) === "load" || _ref === "unload") {
    return node[ast.name].bind(function() {
      return controller[ast.value](node.element, model);
    });
  } else {
    throw new SyntaxError("unkown lifecycle event '" + ast.name + "'");
  }
}

};

Compile = {

element: function(ast, model, controller) {
  var action, child, element, node, property, _i, _j, _len, _len1, _ref, _ref1, _ref2;

  element = Serenade.document.createElement(ast.name);
  node = new Node(ast, element);
  if (ast.id) {
    element.setAttribute('id', ast.id);
  }
  if ((_ref = ast.classes) != null ? _ref.length : void 0) {
    element.setAttribute('class', ast.classes.join(' '));
  }
  node.children = compile(ast.children, model, controller);
  _ref1 = node.children;
  for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
    child = _ref1[_i];
    child.append(element);
  }
  _ref2 = ast.properties;
  for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
    property = _ref2[_j];
    action = Property[property.scope];
    if (action) {
      action(property, node, model, controller);
    } else {
      throw SyntaxError("" + property.scope + " is not a valid scope");
    }
  }
  node.load.trigger();
  return node;
},
view: function(ast, model, parent) {
  var compileView, controller, skipCallback;

  controller = Serenade.controllers[ast.argument];
  if (!controller) {
    skipCallback = true;
    controller = parent;
  }
  compileView = function(dynamic, before, after) {
    var view;

    view = Serenade.views[after].render(model, controller, parent, skipCallback);
    dynamic.replace([view.nodes]);
    return dynamic;
  };
  if (ast.bound) {
    return this.bound(ast, model, controller, compileView);
  } else {
    return compileView(new DynamicNode(ast), void 0, ast.argument);
  }
},
helper: function(ast, model, controller) {
  var argument, context, dynamic, helperFunction, renderBlock, update, _i, _len, _ref;

  dynamic = new DynamicNode(ast);
  renderBlock = function(model, controller) {
    if (model == null) {
      model = model;
    }
    if (controller == null) {
      controller = controller;
    }
    return new View(null, ast.children).render(model, controller);
  };
  helperFunction = Serenade.Helpers[ast.command] || (function() {
    throw SyntaxError("no helper " + ast.command + " defined");
  })();
  context = {
    model: model,
    controller: controller,
    render: renderBlock
  };
  update = function() {
    var args;

    args = ast["arguments"].map(function(a) {
      if (a.bound) {
        return model[a.value];
      } else {
        return a.value;
      }
    });
    return dynamic.replace([normalize(ast, helperFunction.apply(context, args))]);
  };
  _ref = ast["arguments"];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    argument = _ref[_i];
    if (argument.bound === true) {
      dynamic.bindEvent(model["" + argument.value + "_property"], update);
    }
  }
  update();
  return dynamic;
},
text: function(ast, model, controller) {
  var getText, node, textNode;

  getText = function() {
    var value;

    value = getValue(ast, model);
    if (value === 0) {
      value = "0";
    }
    return value || "";
  };
  textNode = Serenade.document.createTextNode(getText());
  node = new Node(ast, textNode);
  if (ast.bound) {
    node.bindEvent(model["" + ast.value + "_property"], function() {
      return assignUnlessEqual(textNode, "nodeValue", getText());
    });
  }
  return node;
},
collection: function(ast, model, controller) {
  var compileItem, dynamic, renderedCollection, update, updateCollection;

  dynamic = null;
  compileItem = function(item) {
    return compile(ast.children, item, controller);
  };
  renderedCollection = [];
  updateCollection = function(_, after) {
    var operation, _i, _len, _ref;

    _ref = Transform(renderedCollection, after);
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      operation = _ref[_i];
      switch (operation.type) {
        case "insert":
          dynamic.insertNodeSet(operation.index, compileItem(operation.value));
          break;
        case "remove":
          dynamic.deleteNodeSet(operation.index);
          break;
        case "swap":
          dynamic.swapNodeSet(operation.index, operation["with"]);
      }
    }
    return renderedCollection = (after != null ? after.map(function(a) {
      return a;
    }) : void 0) || [];
  };
  update = function(dyn, before, after) {
    dynamic = dyn;
    dynamic.unbindEvent(before != null ? before.change : void 0, updateCollection);
    dynamic.bindEvent(after != null ? after.change : void 0, updateCollection);
    return updateCollection(before, after);
  };
  return this.bound(ast, model, controller, update);
},
"in": function(ast, model, controller) {
  return this.bound(ast, model, controller, function(dynamic, _, value) {
    if (value) {
      return dynamic.replace([compile(ast.children, value, controller)]);
    } else {
      return dynamic.clear();
    }
  });
},
"if": function(ast, model, controller) {
  return this.bound(ast, model, controller, function(dynamic, _, value) {
    if (value) {
      return dynamic.replace([compile(ast.children, model, controller)]);
    } else if (ast["else"]) {
      return dynamic.replace([compile(ast["else"].children, model, controller)]);
    } else {
      return dynamic.clear();
    }
  });
},
unless: function(ast, model, controller) {
  return this.bound(ast, model, controller, function(dynamic, _, value) {
    var nodes;

    if (value) {
      return dynamic.clear();
    } else {
      nodes = compile(ast.children, model, controller);
      return dynamic.replace([nodes]);
    }
  });
},
bound: function(ast, model, controller, callback) {
  var dynamic, update;

  dynamic = new DynamicNode(ast);
  update = function(before, after) {
    if (before !== after) {
      return callback(dynamic, before, after);
    }
  };
  update({}, model[ast.argument]);
  dynamic.bindEvent(model["" + ast.argument + "_property"], update);
  return dynamic;
}

};

normalize = function(ast, val) {

var reduction;

if (!val) {
  return [];
}
reduction = function(aggregate, element) {
  var child, div, _i, _j, _len, _len1, _ref, _ref1;

  if (typeof element === "string") {
    div = Serenade.document.createElement("div");
    div.innerHTML = element;
    _ref = div.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      aggregate.push(new Node(ast, child));
    }
  } else if (element.nodeName === "#document-fragment") {
    if (element.nodes) {
      aggregate = aggregate.concat(element.nodes);
    } else {
      _ref1 = element.childNodes;
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        child = _ref1[_j];
        aggregate.push(new Node(ast, child));
      }
    }
  } else {
    aggregate.push(new Node(ast, element));
  }
  return aggregate;
};
return [].concat(val).reduce(reduction, []);

};

compile = function(asts, model, controller) {

var ast, _i, _len, _results;

_results = [];
for (_i = 0, _len = asts.length; _i < _len; _i++) {
  ast = asts[_i];
  _results.push(Compile[ast.type](ast, model, controller));
}
return _results;

};

parser.lexer = {

lex: function() {
  var tag, _ref;

  _ref = this.tokens[this.pos++] || [''], tag = _ref[0], this.yytext = _ref[1], this.yylineno = _ref[2];
  return tag;
},
setInput: function(tokens) {
  this.tokens = tokens;
  return this.pos = 0;
},
upcomingInput: function() {
  return "";
}

};

View = (function() {

function View(name, view) {
  this.name = name;
  this.view = view;
}

View.prototype.parse = function() {
  var e;

  if (typeof this.view === 'string') {
    try {
      return this.view = parser.parse(new Lexer().tokenize(this.view));
    } catch (_error) {
      e = _error;
      if (this.name) {
        e.message = "In view '" + this.name + "': " + e.message;
      }
      throw e;
    }
  } else {
    return this.view;
  }
};

View.prototype.render = function(model, controller, parent, skipCallback) {
  var fragment, node, nodes, _i, _len;

  controller || (controller = Serenade.controllers[this.name] || {});
  if (typeof controller === "function") {
    controller = new controller(model, parent);
  }
  nodes = compile(this.parse(), model, controller);
  if (!skipCallback) {
    if (typeof controller.loaded === "function") {
      controller.loaded.apply(controller, __slice.call(nodes.map(function(node) {
        return node.element;
      })).concat([model]));
    }
  }
  fragment = Serenade.document.createDocumentFragment();
  for (_i = 0, _len = nodes.length; _i < _len; _i++) {
    node = nodes[_i];
    node.append(fragment);
  }
  fragment.nodes = nodes;
  fragment.remove = function() {
    var _j, _len1, _ref, _results;

    _ref = this.nodes;
    _results = [];
    for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
      node = _ref[_j];
      _results.push(node.remove());
    }
    return _results;
  };
  return fragment;
};

return View;

})();

Serenade = function(wrapped) {

var key, object, value;

object = Object.create(wrapped);
for (key in wrapped) {
  value = wrapped[key];
  defineProperty(object, key, {
    value: value
  });
}
return object;

};

extend(Serenade, {

VERSION: '0.5.0',
views: {},
controllers: {},
document: typeof window !== "undefined" && window !== null ? window.document : void 0,
format: format,
defineProperty: defineProperty,
defineEvent: defineEvent,
view: function(nameOrTemplate, template) {
  if (template) {
    return this.views[nameOrTemplate] = new View(nameOrTemplate, template);
  } else {
    return new View(void 0, nameOrTemplate);
  }
},
render: function(name, model, controller, parent, skipCallback) {
  return this.views[name].render(model, controller, parent, skipCallback);
},
controller: function(name, klass) {
  return this.controllers[name] = klass;
},
clearIdentityMap: function() {
  return Cache._identityMap = {};
},
clearCache: function() {
  return Serenade.clearIdentityMap();
},
unregisterAll: function() {
  Serenade.views = {};
  return Serenade.controllers = {};
},
Model: Model,
Collection: Collection,
Cache: Cache,
View: View,
Helpers: {}

});

def(Serenade, “async”, {

get: function() {
  return settings.async;
},
set: function(value) {
  return settings.async = value;
}

}); ;

root.Serenade = Serenade;

}(this));