/**
 * Base class. All other types inherit from this class.
 */

var lAtom = Object.create(null);

lAtom.valueOf = function() {
  return this._value;
};

export var LAtom = function(value) {
  return Object.create(lAtom, { '_value': { value: value } });
};

LAtom.isAtom = value => Object.getPrototypeOf(value) === lAtom;

LAtom.equal = (a, b) => {
  return Object.getPrototypeOf(a) === Object.getPrototypeOf(b) && a.valueOf() === b.valueOf();
};

Object.freeze(lAtom);
Object.freeze(LAtom);


/**
 * LSymbol
 */

var lSymbol = Object.create(lAtom);

export var LSymbol = function(value) {
  return Object.create(lSymbol, { '_value': { value: value } });
};

// This should return true for all values
LSymbol.isSymbol = value => Object.getPrototypeOf(value) === lSymbol;

Object.freeze(lSymbol);
Object.freeze(LSymbol);

/**
 * LNumber
 */

var lNumber = Object.create(lAtom);

export var LNumber = function(value) {
  return Object.create(lNumber, { '_value': { value: Number(value) } });
};

LNumber.isNumber = value => Object.getPrototypeOf(value) === lNumber;

Object.freeze(lNumber);
Object.freeze(LNumber);


/**
 * LString
 */

var lString = Object.create(lAtom);

export var LString = function(value) {
  return Object.create(lString, { '_value': { value: String(value) } });
};

LString.isString = value => Object.getPrototypeOf(value) === lString;

Object.freeze(lString);
Object.freeze(LString);


/**
 * LBoolean
 */

var lBoolean = Object.create(lAtom);

export var LBoolean = function(value) {
  return Object.create(lBoolean, { '_value': { value: value === 'false' ? false : Boolean(value) } });
};

LBoolean.isBoolean = value => Object.getPrototypeOf(value) === lBoolean;

Object.freeze(lBoolean);
Object.freeze(LBoolean);

@@ -1,14 +1,20 @@
 /**%0A *
+ Atom.
  Base cl
@@ -59,16 +59,16 @@
  class.%0A
-
  */%0A%0Avar
@@ -153,16 +153,40 @@
 ue;%0A%7D;%0A%0A
+Object.freeze(lAtom);%0A%0A%0A
 export v
@@ -245,16 +245,52 @@
 lAtom, %7B
+%0A    '_type': %7B value: 'atom' %7D,%0A   
  '_value
@@ -300,32 +300,34 @@
 %7B value: value %7D
+%0A 
  %7D);%0A%7D;%0A%0ALAtom.i
@@ -509,38 +509,16 @@
 ();%0A%7D;%0A%0A
-Object.freeze(lAtom);%0A
 Object.f
@@ -582,32 +582,58 @@
 create(lAtom);%0A%0A
+Object.freeze(lSymbol);%0A%0A%0A
 export var LSymb
@@ -688,16 +688,54 @@
 ymbol, %7B
+%0A    '_type': %7B value: 'symbol' %7D,%0A   
  '_value
@@ -753,16 +753,18 @@
  value %7D
+%0A 
  %7D);%0A%7D;%0A
@@ -881,32 +881,8 @@
 l;%0A%0A
-Object.freeze(lSymbol);%0A
 Obje
@@ -951,32 +951,58 @@
 create(lAtom);%0A%0A
+Object.freeze(lNumber);%0A%0A%0A
 export var LNumb
@@ -1057,16 +1057,54 @@
 umber, %7B
+%0A    '_type': %7B value: 'number' %7D,%0A   
  '_value
@@ -1122,32 +1122,34 @@
  Number(value) %7D
+%0A 
  %7D);%0A%7D;%0A%0ALNumber
@@ -1216,32 +1216,8 @@
 r;%0A%0A
-Object.freeze(lNumber);%0A
 Obje
@@ -1287,32 +1287,58 @@
 create(lAtom);%0A%0A
+Object.freeze(lString);%0A%0A%0A
 export var LStri
@@ -1393,16 +1393,54 @@
 tring, %7B
+%0A    '_type': %7B value: 'string' %7D,%0A   
  '_value
@@ -1458,32 +1458,34 @@
  String(value) %7D
+%0A 
  %7D);%0A%7D;%0A%0ALString
@@ -1552,32 +1552,8 @@
 g;%0A%0A
-Object.freeze(lString);%0A
 Obje
@@ -1633,16 +1633,43 @@
 Atom);%0A%0A
+Object.freeze(lBoolean);%0A%0A%0A
 export v
@@ -1734,16 +1734,55 @@
 olean, %7B
+%0A    '_type': %7B value: 'boolean' %7D,%0A   
  '_value
@@ -1837,16 +1837,18 @@
 value) %7D
+%0A 
  %7D);%0A%7D;%0A
@@ -1926,33 +1926,8 @@
 n;%0A%0A
-Object.freeze(lBoolean);%0A
 Obje

Update types with _type attribute