API Docs for: 1.0

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 === "&omega;"){
			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);
};