package jmathlib.core.tokens;
import jmathlib.core.interpreter.*;
import jmathlib.toolbox.jmathlib.matrix.*;
import jmathlib.core.tokens.numbertokens.DoubleNumberToken;
/**Used to implement assignment operations within an expression*/
public class AssignmentOperatorToken extends BinaryOperatorToken
{
/**
*
*/
public AssignmentOperatorToken()
{
/**call the super constructor, type defaults to ttoperator and operands to 2*/
super('=', ASSIGN_PRIORITY);
}
/** evaluates the operator
* @param operands = the operators operands
* @return the result as and OperandToken
*/
public OperandToken evaluate(Token[] operands, GlobalValues globals)
{
OperandToken result = null;
if (operands.length != 2)
Errors.throwMathLibException("Assignment: operands length != 2");
ErrorLogger.debugLine("AssignmentOperatorToken: eval");
if(operands[0] instanceof VariableToken)
{
// left operand is a variable
ErrorLogger.debugLine("AssignmentOpTok: eval: op is VariableToken");
VariableToken leftVarTok = (VariableToken)operands[0];
// if leftVarTok is of type MathLibObject the next line will return
// a reference to the field values (e.g. a.b)
Variable left = leftVarTok.getVariable(globals);
// check if variable already exists
if (left == null)
{
ErrorLogger.debugLine("AssignmentOpTok: variable is null");
String name = leftVarTok.getName(); // get name of struct
String fieldName = leftVarTok.getFieldName(); // get name of new field name
if (leftVarTok.isCell())
{
// e.g. a{8}=...
ErrorLogger.debugLine("AssignmentOpTok: new cell");
left = globals.createVariable(name);
left.assign(new CellArrayToken());
}
else if (!leftVarTok.isStruct())
{
// auto create a new variable
left = globals.createVariable(name);
}
else if (leftVarTok.isStruct() &&
globals.getVariable(name) == null)
{
// struct is not created yet
ErrorLogger.debugLine("AssignmentOpTok: new struct: "+name+"."+fieldName);
MathLibObject obj = new MathLibObject();
obj.setField(fieldName, DoubleNumberToken.zero);
Variable var = globals.createVariable(name );
var.assign(obj);
left = ((MathLibObject)globals.getVariable(name).getData()).getFieldVariable(fieldName);
}
else
{
// struct is already created, but field is missing
// variable is a struct -> auto create new field variable
ErrorLogger.debugLine("AssignmentOpTok: struct new field: "+name+"."+fieldName);
((MathLibObject)globals.getVariable(name).getData()).setField(fieldName,DoubleNumberToken.zero);
left = leftVarTok.getVariable(globals);
}
}
OperandToken right = ((OperandToken)operands[1]);
// Check if there are limits, because this will result in
// a call to subassign
// e.g. a(1,2)=6
if (leftVarTok.isLimited())
{
ErrorLogger.debugLine("AssignmentOpTok: var has limits");
// create arguments for function call to subassign
OperandToken[] limits = leftVarTok.getLimits();
int limitsLength = limits.length;
OperandToken[] ops = new OperandToken[2+limitsLength];
// clone limits functions/values to preserve for future evalutation
ops[0] = left.getData();
ops[1] = right;
ops[2] = (OperandToken)limits[0].clone();
ops[2] = ops[2].evaluate(null, globals);
if (limitsLength==2)
{
ops[3] = ((OperandToken)limits[1].clone());
ops[3] = ops[3].evaluate(null, globals);
}
subassign subA = new subassign();
if (leftVarTok.isCell())
{
ErrorLogger.debugLine("assign: left is cell");
subA.setLeftCell();
}
// create instance of external function SubAssign and compute assignment
right = subA.evaluate(ops, globals);
}
result = left.assign(right);
//Is this needed??????????????????????????????????
/* display the result this expression in the user console*/
if (isDisplayResult())
{
ErrorLogger.debugLine("AssignmentOperatorToken: displayResult");
if ((right!=null))
globals.getInterpreter().displayText(left.getName() +" = "+ right.toString(globals));
else
globals.getInterpreter().displayText(left.getName() +" = []");
}
return null;
}
else if (operands[0] instanceof Expression)
{
ErrorLogger.debugLine("AssignmentOpTok: eval: Expression *******");
operands[0] = operands[0].evaluate(null, globals);
//return evaluate(operands);
return null;
}
else if (operands[0] instanceof MatrixToken)
{
ErrorLogger.debugLine("AssignOperatorToken: eval: MatrixToken - " + operands[1].toString());
// e.g.: [x,t]=some_function(x)
if (operands[1] instanceof MatrixToken)
{
ErrorLogger.debugLine("AssignOperatorToken: eval: MatrixToken = MatrixToken");
MatrixToken left = (MatrixToken)operands[0];
MatrixToken right = (MatrixToken)operands[1];
if ( (left.getSizeX() != right.getSizeX())
|| (left.getSizeY() != 1)
|| (right.getSizeY() != 1) )
{
ErrorLogger.debugLine("AssignOperatorToken: unequal sizes");
return null;
}
OperandToken[][] leftOps = left.getValue();
OperandToken[][] rightOps = right.getValue();
// assign all right side elements to left side variables
for (int i=0; i<left.getSizeX(); i++)
{
if (!(leftOps[0][i] instanceof VariableToken))
return null;
//ErrorLogger.debugLine("AssignOpToken: inst Var..");
if (!(rightOps[0][i] instanceof DoubleNumberToken ))
return null;
//ErrorLogger.debugLine("AssignOpToken: inst Num..");
// get one variable element of left side
VariableToken varToken = (VariableToken)leftOps[0][i];
Variable leftVar = globals.getVariable(varToken.getName());
// get number-matrix of an element on the right side
DoubleNumberToken number = (DoubleNumberToken)rightOps[0][i];
if (leftVar == null)
{
ErrorLogger.debugLine("AssignmentOpTok: variable is null");
// create variable
leftVar = globals.createVariable(varToken.getName() );
}
// assign right side matrix to left side variable
result = leftVar.assign(number);
}
//return DoubleNumberToken.one;
return null;
}
else if(operands[1] instanceof DoubleNumberToken)
{
ErrorLogger.debugLine("AssignOperatorToken: eval: MatrixToken = DoubleNumberToken");
MatrixToken left = (MatrixToken)operands[0];
DoubleNumberToken right = (DoubleNumberToken)operands[1];
if ( (left.getSizeX() != right.getSizeX())
|| (left.getSizeY() != 1)
|| (right.getSizeY() != 1) )
{
ErrorLogger.debugLine("AssignOperatorToken: unequal sizes");
return null;
}
OperandToken[][] leftOps = left.getValue();
double[][] rightOps = right.getReValues();
// assign all right side elements to left side variables
for (int i=0; i<left.getSizeX(); i++)
{
if (!(leftOps[0][i] instanceof VariableToken))
return null;
//ErrorLogger.debugLine("AssignOpToken: inst Var..");
// get one variable element of left side
VariableToken varToken = ((VariableToken)leftOps[0][i]);
Variable leftVar = globals.getVariable(varToken.getName());
// check if variable already exists
if (leftVar == null)
{
ErrorLogger.debugLine("AssignmentOpTok: variable is null");
// create variable
leftVar = globals.createVariable(varToken.getName() );
}
// get number-matrix of an element on the right side
DoubleNumberToken number = new DoubleNumberToken(rightOps[0][i]);
// assign right side matrix to left side variable
result = leftVar.assign(number);
}
return null;
}
}
else
{
Errors.throwMathLibException(ERR_LVALUE_REQUIRED);
}
return null;
}
}