package org.overture.codegen.trans;
import org.overture.codegen.ir.SExpIR;
import org.overture.codegen.ir.STypeIR;
import org.overture.codegen.ir.analysis.AnalysisException;
import org.overture.codegen.ir.analysis.DepthFirstAnalysisAdaptor;
import org.overture.codegen.ir.declarations.AFieldDeclIR;
import org.overture.codegen.ir.declarations.AMethodDeclIR;
import org.overture.codegen.ir.declarations.AVarDeclIR;
import org.overture.codegen.ir.expressions.AEqualsBinaryExpIR;
import org.overture.codegen.ir.expressions.AFieldNumberExpIR;
import org.overture.codegen.ir.expressions.ANotEqualsBinaryExpIR;
import org.overture.codegen.ir.expressions.ASeqToStringUnaryExpIR;
import org.overture.codegen.ir.expressions.AStringToSeqUnaryExpIR;
import org.overture.codegen.ir.expressions.SBinaryExpIR;
import org.overture.codegen.ir.statements.AAssignToExpStmIR;
import org.overture.codegen.ir.statements.AForAllStmIR;
import org.overture.codegen.ir.statements.AReturnStmIR;
import org.overture.codegen.ir.types.ACharBasicTypeIR;
import org.overture.codegen.ir.types.AMethodTypeIR;
import org.overture.codegen.ir.types.ASeqSeqTypeIR;
import org.overture.codegen.ir.types.AStringTypeIR;
import org.overture.codegen.ir.types.SSeqTypeIR;
import org.overture.codegen.trans.assistants.TransAssistantIR;
public class SeqConvTrans extends DepthFirstAnalysisAdaptor
{
private TransAssistantIR transformationAssistant;
public SeqConvTrans(TransAssistantIR transformationAssistant)
{
this.transformationAssistant = transformationAssistant;
}
@Override
public void caseAForAllStmIR(AForAllStmIR node) throws AnalysisException
{
if (node.getExp().getType() instanceof AStringTypeIR)
{
ASeqSeqTypeIR seqType = new ASeqSeqTypeIR();
seqType.setEmpty(false);
seqType.setSeq1(false);
seqType.setOptional(false);
seqType.setSeqOf(new ACharBasicTypeIR());
correctExpToSeq(node.getExp(), seqType);
}
node.getBody().apply(this);
}
@Override
public void inAFieldDeclIR(AFieldDeclIR node) throws AnalysisException
{
STypeIR nodeType = node.getType();
SExpIR initial = node.getInitial();
handleVarExp(nodeType, initial);
if (initial == null)
{
return;
}
handleExp(initial, nodeType);
}
@Override
public void inAFieldNumberExpIR(AFieldNumberExpIR node)
throws AnalysisException
{
node.getTuple().apply(this);
if (node.getType() instanceof AStringTypeIR)
{
correctExpToString(node);
} else if (node.getType() instanceof SSeqTypeIR)
{
correctExpToSeq(node, node.getType());
}
}
@Override
public void inAVarDeclIR(AVarDeclIR node) throws AnalysisException
{
STypeIR nodeType = node.getType();
SExpIR exp = node.getExp();
handleVarExp(nodeType, exp);
if (exp == null)
{
return;
}
handleExp(exp, nodeType);
}
@Override
public void caseAAssignToExpStmIR(AAssignToExpStmIR node)
throws AnalysisException
{
if (node.getExp() != null)
{
node.getExp().apply(this);
handleExp(node.getExp(), node.getTarget().getType());
}
}
private void handleExp(SExpIR exp, STypeIR nodeType)
{
if (exp.getType() instanceof AStringTypeIR
&& nodeType instanceof SSeqTypeIR)
{
correctExpToSeq(exp, nodeType);
} else if (exp.getType() instanceof SSeqTypeIR
&& nodeType instanceof AStringTypeIR)
{
correctExpToString(exp);
}
}
private void handleVarExp(STypeIR nodeType, SExpIR exp)
throws AnalysisException
{
if (!(nodeType instanceof SSeqTypeIR))
{
return;
}
if (exp != null)
{
exp.apply(this);
}
}
@Override
public void defaultInSBinaryExpIR(SBinaryExpIR node)
throws AnalysisException
{
SExpIR left = node.getLeft();
SExpIR right = node.getRight();
left.apply(this);
right.apply(this);
if (left.getType() instanceof AStringTypeIR
&& right.getType() instanceof AStringTypeIR)
{
node.setType(new AStringTypeIR());
return;
}
if (node.getType() instanceof SSeqTypeIR
|| node instanceof AEqualsBinaryExpIR
|| node instanceof ANotEqualsBinaryExpIR)
{
if (left.getType() instanceof AStringTypeIR
&& right.getType() instanceof SSeqTypeIR)
{
correctExpToString(right);
} else if (right.getType() instanceof AStringTypeIR
&& left.getType() instanceof SSeqTypeIR)
{
correctExpToString(left);
} else
{
return;
}
node.setType(new AStringTypeIR());
}
}
@Override
public void inAReturnStmIR(AReturnStmIR node) throws AnalysisException
{
SExpIR exp = node.getExp();
if (exp != null)
{
exp.apply(this);
} else
{
return;
}
AMethodDeclIR method = node.getAncestor(AMethodDeclIR.class);
AMethodTypeIR methodType = method.getMethodType();
if (methodType.getResult() instanceof AStringTypeIR)
{
if (!(exp.getType() instanceof SSeqTypeIR))
{
return;
}
correctExpToString(exp);
;
} else if (methodType.getResult() instanceof SSeqTypeIR)
{
if (!(exp.getType() instanceof AStringTypeIR))
{
return;
}
correctExpToSeq(exp, exp.getType());
}
}
private void correctExpToSeq(SExpIR toCorrect, STypeIR type)
{
AStringToSeqUnaryExpIR conversion = new AStringToSeqUnaryExpIR();
transformationAssistant.replaceNodeWith(toCorrect, conversion);
conversion.setType(type.clone());
conversion.setExp(toCorrect);
}
private void correctExpToString(SExpIR toCorrect)
{
ASeqToStringUnaryExpIR conversion = new ASeqToStringUnaryExpIR();
transformationAssistant.replaceNodeWith(toCorrect, conversion);
conversion.setType(new AStringTypeIR());
conversion.setExp(toCorrect);
}
}