function setValue( v ) {
	document.calc.bar.value = v;
}

function getValue() {
	return document.calc.bar.value;
}

function push( v ) {
	stack[stacktop] = v;
	document.calc.stack.options[stacktop] = new Option( v, v );
	stacktop = stacktop + 1;
}

function pop()
{
	if( stacktop < 1 ) {
		alert( "堆疊是空的" );
		return;
	}

	stacktop = stacktop - 1;
	v = stack[stacktop];
	document.calc.stack.options[stacktop] = null;

	return v;
}

function top()
{
	if( stacktop < 1 ) {
		alert( "堆疊是空的" );
		return;
	}

	setValue( stack[stacktop - 1] );
}

function swap()
{
	if( stacktop < 2 ) {
		alert( "堆疊中元素個數不足，無法交換" );
		return;
	}

	v1 = pop();
	v2 = pop();
	push( v1 );
	push( v2 );
}

function dup()
{
	if( stacktop < 1 ) {
		alert( "堆疊中元素個數不足，無法複製" );
		return;
	}

	push( stack[stacktop - 1] );
}

function factorial( n ) {
	var prod = 1;
	for( i = 1; i <= n; i++) {
		prod *= i;
	}
	return prod;
}

function choose( m, n ) {
	return factorial(m) / factorial(n) / factorial(m - n);
}

function perm( m, n ) {
	return factorial(m) / factorial(m - n);
}

function binary( op )
{
	if( stacktop < 2 ) {
		alert('運算子不足');
		return;
	}

	op2 = pop();
	op1 = pop();

	if( op == "add" ) {
		result = op1 + op2;
	} else if( op == "sub" ) {
		result = op1 - op2;
	} else if( op == "mul" ) {
		result = op1 * op2;
	} else if( op == "div" ) {
		result = op1 / op2;
	} else if( op == "mod" ) {
		result = op1 % op2;
	} else if( op == "pow" ) {
		result = Math.pow( op1, op2 );
	} else if( op == "choose" ) {
		result = choose( op1, op2 );
	} else if( op == "perm" ) {
		result = perm( op1, op2 );
	}

	push( result );
}

function uniary( op )
{
	if( stacktop < 1 ) {
		alert('運算子不足');
		return;
	}

	operand = pop();

	if( op == "factorial" ) {
		result = fac( operand );
	} else if( op == "sqrt" ) {
		result = Math.sqrt( operand );
	} else if( op == "pow2" ) {
		result = operand * operand ;
	} else if( op == "reverse" ) {
		result = 1 / operand;
	} else if( op == "sin" ) {
		result = Math.sin( operand );
	} else if( op == "cos" ) {
		result = Math.cos( operand );
	} else if( op == "tan" ) {
		result = Math.tan( operand );
	} else if( op == "asin" ) {
		result = Math.asin( operand );
	} else if( op == "acos" ) {
		result = Math.acos( operand );
	} else if( op == "atan" ) {
		result = Math.atan( operand );
	}

	push( result );
}

function ln( b )
{
	if( stacktop < 1 ) {
		alert('運算子不足');
		return;
	}

	operand = pop();
	push( Math.log( operand ) / Math.log( b ) );
}

function pi()
{
	setValue( Math.PI );
}

function e()
{
	setValue( Math.E );
}

function pushInput()
{
	push( textToNum( getValue() ) );
	setValue( 0 );
}

function popInput()
{
	v = pop();
	if( v ) {
		setValue( v );
	}
}

function Append( text )
{
	if( text == "." ) {
		if( getValue().indexOf( "." ) == -1 ) {
			setValue( getValue() + text );
		}
		return;
	}

	if( getValue() == "0" ) {
		setValue( text.toString() );
		return;
	}

	setValue( getValue() + text.toString() );
}

function changeSign()
{
	if( getValue().charAt( 0 ) == "-" ) {
		setValue( getValue().substr(1) );
	} else {
		setValue( "-" + getValue() );
	}
}

function clearInput()
{
	setValue( 0 );
}

function allclear()
{
	while( stacktop > 0 ) {
		pop();
	}
	setValue( 0 );
}

function getkey( e ) {

	// alert( e.keyCode );
	// alert( e.which );

	// FIXME
	key = e.which;
	num = e.which - 48;

	if( num >= 0 && num <= 9 ) {
		Append( num );
		return;
	}

	// ESC
	if( e.keyCode == 27 ) {
		setValue( 0 );
		return;
	}

	switch( key ) {
		case 13:
			pushInput();
			break;
		case 42:
			binary('mul');
			break;
		case 43:
			binary('add');
			break;
		case 45:
			binary('sub');
			break;
		case 46:
			Append('.');
			break;
		case 47:
			binary('div');
			break;
	};
}

function init()
{
	stack = new Array( 128 );
	stacktop = 0;
	setValue( 0 );
}

