src/js/stackEl.js
/*! @file stackEl.js */
/*
* part of the 'Transfinite Ordinal Calculator'
* author: Claudio Kressibucher
* license: GNU LGPL
*/
// this file defines some classes for the data stored on the model stack
/* JSHINT global declaration */
/*global config:true, util:true, oGui:true, model:true, OrdSummand:true, Ord:true, ClassedError:true, Calculation:true */
//============================================================== //
//============ Class model.StackEl ============================= //
//============================================================== //
/**
* The abstract superclass defining all elements
* of the model stack.
* @class StackEl
* @constructor
*/
model.StackEl = function StackEl(){
/**
* Type of StackElement
* @property t
* @type number (Value from model.enumType)
* @private
*/
this.t = model.enumType.tUnvalid;
};
/**
* Get the type of this Stack Element.
* @method getType
* @return {number} The type. A value form model.enumType.
*/
model.StackEl.prototype.getType = function (){
return this.t;
};
/**
* Serializes the data of this stack element and
* appends the component(s) to the array given as
* parameter
* @method serialize
* @param {array} arr The Array to which the data will be appended.
* @param {boolean} htmlStyle. If true, the serialization
* generates a html representation.
*/
model.StackEl.prototype.serialize = function(arr, sep){
oGui.dbgErr("StackEl.serialize: should be overriden by Subclasses!");
};
//============================================================== //
//============ Class model.Operand ============================= //
//============================================================== //
/**
* This class defines the operand elements
* of the model stack (containing Ord objects or natural numbers as values).
* @class Operand
* @constructor
* @extends StackEl
*/
model.Operand = function (type){
// See StackEl.t
this.t = type || model.enumType.tUnvalid;
/**
* The value of the operand. Contains either an
* object of type Ord (if t == tOrd) or a String
* representing the value of a natural number
* or a constant (if t == tNatNum or t === tConst
* respectively)
* @property v
* @type Ord / string
* @private
*/
this.v = null;
};
// set prototype and reset constructor function
model.Operand.prototype = new model.StackEl();
model.Operand.prototype.constructor = model.Operand;
// methods
/**
* Get the value of this Stack Element as an
* instance of the class <pre>Ord</pre>.
* @method getOrd
* @return {Ord} The value of this stack element
*/
model.Operand.prototype.getOrd = function (){
var o;
if (this.t === model.enumType.tOrd){
return this.v;
}
// else
o = new Ord();
if (this.t === model.enumType.tNatNum) {
o.addSummand(new OrdSummand(0, this.v));
} else if (this.t === model.enumType.tConst) {
o.addSummand(new OrdSummand(1, 1));
} else {
oGui.dbgErr("wrong type: this.t = " + this.t +
" but should be an operand");
return null;
}
return o;
};
/**
* Get the value of this operand, either as javascript number object
* (if this.t == enumType.tNatNum) or as string (if this.t === tConst)
* or as Ord object (if the value contains such an object).
* May throw a ClassedError.
* @method getValue
* @return {number / Ord} The value contained in this Operand element.
*/
model.Operand.prototype.getValue = function (){
var num;
if (this.t === model.enumType.tNatNum){
if (typeof(this.v) === 'number')
return this.v;
else {
num = this.v*1;
if (this.v === num.toString())
return num;
else {
throw new ClassedError("number to great: inaccurrate calculation", ClassedError.types.inaccurate);
}
}
}
return this.v;
};
/**
* Set the value of this Operand element.
* May throw a ClassedError.
* @method setValue
* @param {number / Ord} val The value to set. Its type must correspond
* to the defined type of this Operand
*/
model.Operand.prototype.setValue = function (val){
if (config.debug > 0){
if (this.t === model.enumType.tNatNum){
util.assert(typeof(val) === 'number' || typeof(val) === 'string');
} else if (this.t === model.enumType.tConst){
util.assert(typeof(val) === 'string');
} else {
util.assert(this.t === model.enumType.tOrd);
util.assert(val instanceof Ord);
}
}
if (this.t === model.enumType.tNatNum){
if (typeof(val) === 'string'){
val = parseInt(val, 10);
} else if (typeof(val) !== 'number'){
throw new ClassedError("", ClassedError.types.progError);
}
// type of val is number
if (!Calculation.sIsValidNatural(val)){
throw new ClassedError("number to great: inaccurrate calculation", ClassedError.types.inaccurate);
}
}
this.v = val;
};
/**
* Checks if there is a value set for this Operand.
* @method isValueSet
* @return {boolean} True if a value is set
*/
model.Operand.prototype.isValueSet = function (){
return this.v !== null;
};
/**
* Serializes the data of this Operand and
* appends the single components to the array given as
* parameter
* @method serialize
* @param {array} arr The Array to which the data will be appended.
* @param {boolean} htmlStyle. If true, the serialization
* generates a html representation.
*/
model.Operand.prototype.serialize = function(arr, htmlStyle){
if (this.v instanceof Ord){
this.v.serialize(arr, htmlStyle);
} else {
if (!htmlStyle && this.getType() === model.enumType.tConst && this.v === "ω"){
arr.push('w');
} else {
arr.push(this.v);
}
}
};
//============================================================== //
//============ Class model.Operator ============================ //
//============================================================== //
/**
* An Operator represents the symbol of a mathematical
* operator.
* @class Operator
* @param {string} symbol The character representing the operator.
* Might be a '^' (exponentiation), '*' (multiplication) or a '+'
* (Addition).
* @constructor
* @extends StackEl
*/
model.Operator = function (symbol){
/**
* The symbol of the mathematical operator. Possible values are
* contained in model.Operator.prioDef object.
* @property sym
* @type string
* @private
*/
this.sym = symbol;
if ( !this.prioDef[symbol] ){
oGui.dbgErr("Operator constructor: wrong symbol: " + symbol + " : " + this.prioDef[symbol]);
}
// See StackEl.t
this.t = model.enumType.tOptor;
};
// set the superclass (StackEl) and reset the constructor
model.Operator.prototype = new model.StackEl();
model.Operator.prototype.constructor = model.Operator;
/**
* Defines the priority of the mathematical operators.
* The operator symbols are the keys, the priority (number)
* are the values. A higher value means a
* higher priority in calculation.
* @property prioDef
* @type Object literal containing pairs of string-int (key-value)
*/
model.Operator.prototype.prioDef = {
'^' : 8,
'*' : 6,
'+' : 4
};
/**
* Get the priority of this Operator. A higher value means a
* higher priority in calculation.
* @method getPrio
* @return {number} The priority
*/
model.Operator.prototype.getPrio = function (){
if ( this.prioDef[this.sym] ){
return this.prioDef[this.sym];
}
// fatal error, exits further execution
oGui.progError("model.Operator.getPrio: Operator " + this.sym + " is not defined in prioDef object.");
};
/**
* Get the symbol of the operator.
* @method getSymbol
* @return {string} The symbol
*/
model.Operator.prototype.getSymbol = function (){
return this.sym;
};
/**
* Serializes the data of this Operator and
* appends the (only) component, the symbol, to the array given as
* parameter
* @method serialize
* @param {array} arr The Array to which the data will be appended.
* @param {boolean} htmlStyle. If true, the serialization
* generates a html representation.
*/
model.Operator.prototype.serialize = function(arr, sep){
arr.push(this.sym);
};
//============================================================== //
//============ Class model.Bracket ============================= //
//============================================================== //
/**
* This class defines the bracket elements
* (representing opening and closing brackets)
* of the model stack.
* @class Bracket
* @param {string} symbol May be a '(' or a ')' for left or right bracket respectively.
* @constructor
* @extends StackEl
*/
model.Bracket = function (symbol){
/**
* The symbol of the bracket repesenting as sting. Possible values are
* '(' and ')'.
* @property sym
* @type string
* @private
*/
this.sym = symbol;
if (symbol !== '(' && symbol !== ')'){
oGui.dbgErr("wrong symbol for Bracket constructor: " + symbol);
}
// See StackEl.t
this.t = model.enumType.tBracket;
};
// set superclass and reset constructor
model.Bracket.prototype = new model.StackEl();
model.Bracket.prototype.constructor = model.Bracket;
/**
* Checks if this bracket is a left (opening) bracket
* @method isLeft
* @return {boolean} True, if this Bracket object contains a left bracket.
*/
model.Bracket.prototype.isLeft = function (){
return this.sym === '(';
};
/**
* Checks if this bracket is a right (closing) bracket
* @method isRight
* @return {boolean} True, if this Bracket object contains a right bracket.
*/
model.Bracket.prototype.isRight = function (){
return this.sym === ')';
};
/**
* Get the string representation of the bracket.
* @method getSymbol
* @return {string} The symbol
*/
model.Bracket.prototype.getSymbol = function (){
return this.sym;
};
/**
* Serializes the data of this Bracket and
* appends the (only) component, the symbol, to the array given as
* parameter
* @method serialize
* @param {array} arr The Array to which the data will be appended.
* @param {boolean} htmlStyle. If true, the serialization
* generates a html representation.
*/
model.Bracket.prototype.serialize = function(arr, sep){
arr.push(this.sym);
};