Add structure for unification texts

This commit is contained in:
Moritz Dieing 2021-08-09 13:02:01 +02:00
parent 69479a6368
commit 6968a4b5f2
2 changed files with 401 additions and 112 deletions

View File

@ -1,12 +1,14 @@
package edu.kit.typicalc.view.content.typeinferencecontent.latexcreator; package edu.kit.typicalc.view.content.typeinferencecontent.latexcreator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Optional;
import java.util.Queue; import java.util.Queue;
import com.vaadin.flow.i18n.I18NProvider;
import edu.kit.typicalc.model.TypeInfererInterface;
import edu.kit.typicalc.model.step.AbsStep; import edu.kit.typicalc.model.step.AbsStep;
import edu.kit.typicalc.model.step.AbsStepDefault; import edu.kit.typicalc.model.step.AbsStepDefault;
import edu.kit.typicalc.model.step.AbsStepWithLet; import edu.kit.typicalc.model.step.AbsStepWithLet;
@ -28,227 +30,242 @@ import edu.kit.typicalc.model.type.TypeArgumentVisitor;
import edu.kit.typicalc.model.term.LambdaTerm; import edu.kit.typicalc.model.term.LambdaTerm;
import edu.kit.typicalc.view.TypicalcI18NProvider; import edu.kit.typicalc.view.TypicalcI18NProvider;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.TEXT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.CURLY_LEFT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.CURLY_RIGHT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.DOLLAR_SIGN;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.SPACE;
public class ExplanationCreator implements StepVisitor { public class ExplanationCreator implements StepVisitor {
private final TypicalcI18NProvider provider = new TypicalcI18NProvider(); private static final String KEY_PREFIX = "explanationTree.";
private final I18NProvider provider = new TypicalcI18NProvider();
private final TermArgumentVisitor termArgumentVisitor = new TermArgumentVisitor(); private final TermArgumentVisitor termArgumentVisitor = new TermArgumentVisitor();
private final TypeArgumentVisitor typeArgumentVisitor = new TypeArgumentVisitor(); private final TypeArgumentVisitor typeArgumentVisitor = new TypeArgumentVisitor();
private final Locale locale;
private final Map<Locale, List<String>> explanationTexts = new HashMap<>(); private final List<String> explanationTexts = new ArrayList<>();
private static final LatexCreatorMode MODE = LatexCreatorMode.MATHJAX; private static final LatexCreatorMode MODE = LatexCreatorMode.MATHJAX;
private boolean errorOccurred; // true if one unification was not successful
private int letCounter = 0; // count number of lets for unification indices
public ExplanationCreator() { // creates explanation texts for a specific language
provider.getProvidedLocales().forEach(l -> explanationTexts.put(l, new ArrayList<String>())); public ExplanationCreator(TypeInfererInterface typeInferer, Locale locale) {
this.locale = locale;
errorOccurred = false;
explanationTexts.add(createInitialText(typeInferer));
typeInferer.getFirstInferenceStep().accept(this);
if (!errorOccurred) {
explanationTexts.addAll(new ExplanationCreatorUnification(typeInferer, locale, provider, MODE,
letCounter, false, Optional.empty()).getUnificationsTexts().getLeft());
}
} }
public Map<Locale, List<String>> getExplanationTexts() { public List<String> getExplanationTexts() {
return explanationTexts; return explanationTexts;
} }
private String getDefaultTextLatex(String textKey, Locale locale) { private String getDefaultTextLatex(String textKey) {
return new StringBuilder(LatexCreatorConstants.TEXT + LatexCreatorConstants.CURLY_LEFT). return new StringBuilder(TEXT + CURLY_LEFT).
append(provider.getTranslation(textKey, locale)). append(provider.getTranslation(textKey, locale)).
append(LatexCreatorConstants.CURLY_RIGHT) append(CURLY_RIGHT)
.toString(); .toString();
} }
private String toLatex(String latex) { private String toLatex(String latex) {
return LatexCreatorConstants.DOLLAR_SIGN + latex + LatexCreatorConstants.DOLLAR_SIGN; return SPACE + DOLLAR_SIGN + latex + DOLLAR_SIGN + SPACE;
}
private String createInitialText(TypeInfererInterface typeInferer) {
String typeLatex = new LatexCreatorType(typeInferer.getFirstInferenceStep().getConclusion().getType(), MODE).
getLatex();
return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "initial1")).
append(toLatex(new LatexCreatorTerm(
typeInferer.getFirstInferenceStep().getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex(KEY_PREFIX + "initial2")).
append(toLatex(typeLatex)).
append(getDefaultTextLatex(KEY_PREFIX + "initial3")).
append(toLatex(typeLatex)).
append(getDefaultTextLatex(KEY_PREFIX + "initial4")).
toString();
} }
@Override @Override
public void visit(AbsStepDefault absD) { public void visit(AbsStepDefault absD) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexAbsStep(absD));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexAbsStep(absD, l));
explanationTexts.put(l, texts);
});
absD.getPremise().accept(this); absD.getPremise().accept(this);
} }
@Override @Override
public void visit(AbsStepWithLet absL) { public void visit(AbsStepWithLet absL) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexAbsStep(absL));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexAbsStep(absL, l));
explanationTexts.put(l, texts);
});
absL.getPremise().accept(this); absL.getPremise().accept(this);
} }
private String createLatexAbsStep(AbsStep abs, Locale locale) { private String createLatexAbsStep(AbsStep abs) {
Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(abs.getConclusion().getLambdaTerm()); Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(abs.getConclusion().getLambdaTerm());
Queue<Type> typeArguments = typeArgumentVisitor.getArguments(abs.getConstraint().getSecondType()); Queue<Type> typeArguments = typeArgumentVisitor.getArguments(abs.getConstraint().getSecondType());
return new StringBuilder(getDefaultTextLatex("key", locale)). return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "absStep1")).
append(toLatex(new LatexCreatorTerm(abs.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(abs.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep2")).
append(toLatex(new LatexCreatorType(abs.getConclusion().getType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(abs.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep3")).
append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep4")).
append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep5")).
append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep6")).
append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep7")).
append(toLatex(new LatexCreatorType(abs.getConstraint().getSecondType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(abs.getConstraint().getSecondType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep8")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(abs.getConstraint(), MODE))). append(toLatex(LatexCreatorConstraints.createSingleConstraint(abs.getConstraint(), MODE))).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "absStep9")).
toString(); toString();
} }
@Override @Override
public void visit(AppStepDefault appD) { public void visit(AppStepDefault appD) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexAppStep(appD));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexAppStep(appD, l));
explanationTexts.put(l, texts);
});
appD.getPremise1().accept(this); appD.getPremise1().accept(this);
appD.getPremise2().accept(this); appD.getPremise2().accept(this);
} }
private String createLatexAppStep(AppStep app, Locale locale) { private String createLatexAppStep(AppStep app) {
Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(app.getConclusion().getLambdaTerm()); Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(app.getConclusion().getLambdaTerm());
Queue<Type> typeArguments = typeArgumentVisitor.getArguments(app.getConstraint().getSecondType()); Queue<Type> typeArguments = typeArgumentVisitor.getArguments(app.getConstraint().getSecondType());
return new StringBuilder(getDefaultTextLatex("key", locale)). return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "appStep1")).
append(toLatex(new LatexCreatorTerm(app.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(app.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep2")).
append(toLatex(new LatexCreatorType(app.getConclusion().getType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(app.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep3")).
append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep4")).
append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep5")).
append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep6")).
append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorType(typeArguments.poll(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep7")).
append(toLatex(new LatexCreatorType(app.getConstraint().getSecondType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(app.getConstraint().getSecondType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep8")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(app.getConstraint(), MODE))). append(toLatex(LatexCreatorConstraints.createSingleConstraint(app.getConstraint(), MODE))).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "appStep9")).
toString(); toString();
} }
@Override @Override
public void visit(ConstStepDefault constD) { public void visit(ConstStepDefault constD) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexConstStep(constD));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexConstStep(constD, l));
explanationTexts.put(l, texts);
});
} }
private String createLatexConstStep(ConstStep constS, Locale locale) { private String createLatexConstStep(ConstStep constS) {
return new StringBuilder(getDefaultTextLatex("key", locale)). return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "constStep1")).
append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep2")).
append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep3")).
append(toLatex(new LatexCreatorType(constS.getConclusion().getType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(constS.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep4")).
append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(constS.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep5")).
append("$" + constS.getConclusion().getType() + "$"). append(toLatex(new LatexCreatorType(constS.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep6")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(constS.getConstraint(), MODE))). append(toLatex(LatexCreatorConstraints.createSingleConstraint(constS.getConstraint(), MODE))).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "constStep7")).
toString(); toString();
} }
@Override @Override
public void visit(VarStepDefault varD) { public void visit(VarStepDefault varD) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexVarStep(varD));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexVarStep(varD, l));
explanationTexts.put(l, texts);
});
} }
@Override @Override
public void visit(VarStepWithLet varL) { public void visit(VarStepWithLet varL) {
provider.getProvidedLocales().forEach(l -> { explanationTexts.add(createLatexVarStep(varL));
List<String> texts = explanationTexts.get(l);
texts.add(createLatexVarStep(varL, l));
explanationTexts.put(l, texts);
});
// TODO: maybe create slightly different text // TODO: maybe create slightly different text
} }
private String createLatexVarStep(VarStep varS, Locale locale) { private String createLatexVarStep(VarStep varS) {
String termLatex = new LatexCreatorTerm(varS.getConclusion().getLambdaTerm(), MODE).getLatex();
return new StringBuilder(getDefaultTextLatex("key", locale)). return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "varStep1")).
append(toLatex(new LatexCreatorTerm(varS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(termLatex)).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep2")).
append(toLatex(new LatexCreatorTerm(varS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(termLatex)).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep3")).
append(toLatex(new LatexCreatorType(varS.getConclusion().getType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(varS.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep4")).
append(toLatex(new LatexCreatorTerm(varS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(termLatex)).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep5")).
append(toLatex(new LatexCreatorType(varS.getConstraint().getSecondType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(varS.getConstraint().getSecondType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep6")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(varS.getConstraint(), MODE))). append(toLatex(LatexCreatorConstraints.createSingleConstraint(varS.getConstraint(), MODE))).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "varStep7")).
toString(); toString();
} }
@Override @Override
public void visit(LetStepDefault letD) { public void visit(LetStepDefault letD) {
provider.getProvidedLocales().forEach(l -> { Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(letD.getConclusion().getLambdaTerm());
List<String> texts = explanationTexts.get(l);
texts.add(createLatexLetStep(letD, l));
explanationTexts.put(l, texts);
});
letD.getPremise().accept(this);
}
private String createLatexLetStep(LetStep letS, Locale locale) {
Queue<LambdaTerm> termArguments = termArgumentVisitor.getArguments(letS.getConclusion().getLambdaTerm());
LambdaTerm variable = termArguments.poll(); LambdaTerm variable = termArguments.poll();
LambdaTerm innerTerm = termArguments.poll(); LambdaTerm innerTerm = termArguments.poll();
LambdaTerm variableDefinition = termArguments.poll();
letCounter++;
explanationTexts.add(createLatexLetStep(letD, variable, innerTerm, variableDefinition));
return new StringBuilder(getDefaultTextLatex("key", locale)). letD.getTypeInferer().getFirstInferenceStep().accept(this);
ExplanationCreatorUnification unification =
new ExplanationCreatorUnification(letD.getTypeInferer(), locale, provider, MODE, letCounter, true,
Optional.of(variable));
explanationTexts.addAll(unification.getUnificationsTexts().getLeft());
errorOccurred = unification.getUnificationsTexts().getRight();
letCounter--;
if (!errorOccurred) {
letD.getPremise().accept(this);
}
}
private String createLatexLetStep(LetStep letS, LambdaTerm variable, LambdaTerm innerTerm,
LambdaTerm variableDefinition) {
return new StringBuilder(getDefaultTextLatex(KEY_PREFIX + "letStep1")).
append(toLatex(new LatexCreatorTerm(letS.getConclusion().getLambdaTerm(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(letS.getConclusion().getLambdaTerm(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep2")).
append(toLatex(new LatexCreatorType(letS.getConclusion().getType(), MODE).getLatex())). append(toLatex(new LatexCreatorType(letS.getConclusion().getType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep3")).
append(toLatex(new LatexCreatorTerm(variable, MODE).getLatex())). append(toLatex(new LatexCreatorTerm(variable, MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep4")).
append(toLatex(new LatexCreatorTerm(termArguments.poll(), MODE).getLatex())). append(toLatex(new LatexCreatorTerm(variableDefinition, MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep5")).
append(toLatex(new LatexCreatorTerm(innerTerm, MODE).getLatex())). append(toLatex(new LatexCreatorTerm(innerTerm, MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep6")).
append(toLatex(new LatexCreatorTerm(variableDefinition, MODE).getLatex())).
append(getDefaultTextLatex(KEY_PREFIX + "letStep7")).
append(toLatex(new LatexCreatorTerm(variable, MODE).getLatex())). append(toLatex(new LatexCreatorTerm(variable, MODE).getLatex())).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep8")).
append(toLatex(new LatexCreatorTerm(innerTerm, MODE).getLatex())).
append(getDefaultTextLatex("key", locale)).
append(toLatex(new LatexCreatorType(letS.getConstraint().getSecondType(), MODE).getLatex())).
append(getDefaultTextLatex("key", locale)).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(letS.getConstraint(), MODE))). append(toLatex(LatexCreatorConstraints.createSingleConstraint(letS.getConstraint(), MODE))).
append(getDefaultTextLatex("key", locale)). append(getDefaultTextLatex(KEY_PREFIX + "letStep9")).
toString(); toString();
} }
@Override @Override
public void visit(EmptyStep empty) { public void visit(EmptyStep empty) {
// TODO Auto-generated method stub
} }
@Override @Override
public void visit(OnlyConclusionStep onlyConc) { public void visit(OnlyConclusionStep onlyConc) {
// TODO Auto-generated method stub
} }
} }

View File

@ -0,0 +1,272 @@
package edu.kit.typicalc.view.content.typeinferencecontent.latexcreator;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.AssumptionGeneratorUtil.typeAssumptionsToLatex;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.AMPERSAND;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.BRACKET_LEFT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.BRACKET_RIGHT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.COMMA;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.LATEX_NEW_LINE;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.SUBSTITUTION_SIGN;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.TYPE_ABSTRACTION;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.CURLY_LEFT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.CURLY_RIGHT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.LET;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.PAREN_LEFT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.PAREN_RIGHT;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.UNDERSCORE;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.CONSTRAINT_SET;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.GAMMA;
import static edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreatorConstants.SIGMA;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Queue;
import org.apache.commons.lang3.tuple.Pair;
import com.vaadin.flow.i18n.I18NProvider;
import edu.kit.typicalc.model.Constraint;
import edu.kit.typicalc.model.Substitution;
import edu.kit.typicalc.model.TypeInfererInterface;
import edu.kit.typicalc.model.UnificationError;
import edu.kit.typicalc.model.UnificationStep;
import edu.kit.typicalc.model.term.LambdaTerm;
import edu.kit.typicalc.model.type.Type;
import edu.kit.typicalc.model.type.TypeArgumentVisitor;
import edu.kit.typicalc.util.Result;
public class ExplanationCreatorUnification {
private final TypeArgumentVisitor typeDeterminer = new TypeArgumentVisitor();
private final TypeInfererInterface typeInferer;
private final Locale locale;
private final I18NProvider provider;
private final LatexCreatorMode mode;
private final int letCounter;
private final Optional<LambdaTerm> letVariable;
private final List<String> unificationTexts = new ArrayList<>();
private boolean errorOccurred;
public ExplanationCreatorUnification(TypeInfererInterface typeInferer, Locale locale, I18NProvider provider,
LatexCreatorMode mode, int letCounter, boolean isLetUnification, Optional<LambdaTerm> letVariable) {
this.typeInferer = typeInferer;
this.locale = locale;
this.provider = provider;
this.mode = mode;
this.letCounter = letCounter;
this.letVariable = letVariable;
buildTexts(isLetUnification);
}
public Pair<List<String>, Boolean> getUnificationsTexts() {
return Pair.of(unificationTexts, errorOccurred);
}
private void buildTexts(boolean isLetUnification) {
String initialStepKey = isLetUnification ? "key1" : "key2";
unificationTexts.add(getDefaultTextLatex(initialStepKey));
createUnficationTexts();
if (!errorOccurred) {
createMGU();
createFinalType(isLetUnification);
if (isLetUnification) {
createLetUnficiationFinish();
}
}
}
private void createLetUnficiationFinish() {
String typeAssumptions =
typeAssumptionsToLatex(typeInferer.getFirstInferenceStep().getConclusion().getTypeAssumptions(), mode);
String letVariableLatex = new LatexCreatorTerm(this.letVariable.get(), mode).getLatex();
StringBuilder latex = new StringBuilder(getDefaultTextLatex("key")).
append(toLatex(GAMMA)).
append(getDefaultTextLatex("key")).
append(toLatex(letCounterToLatex(SIGMA))).
append(toLatex(GAMMA)).
append(getDefaultTextLatex("key")).
append(toLatex(letVariableLatex)).
append(getDefaultTextLatex("key")).
append(toLatex(createTypeAbstraction(typeAssumptions))).
append(getDefaultTextLatex("key")).
append(toLatex(letVariableLatex)).
append(getDefaultTextLatex("key")).
append(toLatex(GAMMA)).
append(getDefaultTextLatex("key")).
append(new LatexCreatorType(typeInferer.getType().get(), mode).getLatex()).
append(getDefaultTextLatex("key")).
append(toLatex(letCounterToLatex(SIGMA) + PAREN_LEFT + typeAssumptions + "" + PAREN_RIGHT)).
append(getDefaultTextLatex("key"));
unificationTexts.add(latex.toString());
// add "second part" of let step here, so that the letCounterToLatex method can still be used
latex = new StringBuilder(getDefaultTextLatex("key")).
append(toLatex(letCounterToLatex(CONSTRAINT_SET))).
append(getDefaultTextLatex("key"));
unificationTexts.add(latex.toString());
}
private String createTypeAbstraction(String typeAssumptions) {
return new StringBuilder(TYPE_ABSTRACTION + PAREN_LEFT + letCounterToLatex(SIGMA)).
append(new LatexCreatorType(typeInferer.getFirstInferenceStep().getConclusion().getType(), mode)
.getLatex()).
append("" + PAREN_RIGHT + COMMA + letCounterToLatex(SIGMA) + PAREN_LEFT).
append(typeAssumptions).
append("" + PAREN_RIGHT + PAREN_RIGHT).toString();
}
private void createFinalType(boolean isLetUnification) {
String keyPrefix = isLetUnification ? "let" : "";
StringBuilder latex = new StringBuilder(getDefaultTextLatex(keyPrefix + "key")).
append(toLatex(letCounterToLatex(SIGMA))).
append(getDefaultTextLatex(keyPrefix + "key")).
append(toLatex(new LatexCreatorType(typeInferer.getFirstInferenceStep().getConclusion().getType(), mode)
.getLatex())).
append(getDefaultTextLatex(keyPrefix + "key")).
append(toLatex(new LatexCreatorType(typeInferer.getType().get(), mode).getLatex())).
append(getDefaultTextLatex(keyPrefix + "key"));
unificationTexts.add(latex.toString());
}
private void createMGU() {
StringBuilder latex = new StringBuilder(getDefaultTextLatex("key")).
append(toLatex(letCounterToLatex(SIGMA))).
append(getDefaultTextLatex("key")).
append(toLatex(letCounterToLatex(CONSTRAINT_SET))).
append(getDefaultTextLatex("key"));
unificationTexts.add(latex.toString());
}
private String getDefaultTextLatex(String textKey) {
return new StringBuilder(LatexCreatorConstants.TEXT + LatexCreatorConstants.CURLY_LEFT).
append(provider.getTranslation(textKey, locale)).
append(LatexCreatorConstants.CURLY_RIGHT)
.toString();
}
// WARNING: call toLatex() before to get proper latex code
private String letCounterToLatex(String setName) {
switch (letCounter) {
case 0:
return setName;
case 1:
return setName + UNDERSCORE + CURLY_LEFT + LET + CURLY_RIGHT;
default:
return setName + UNDERSCORE + CURLY_LEFT + LET + CURLY_LEFT + letCounter
+ CURLY_RIGHT + CURLY_RIGHT;
}
}
private String toLatex(String latex) {
return LatexCreatorConstants.DOLLAR_SIGN + latex + LatexCreatorConstants.DOLLAR_SIGN;
}
private String getSubstitutionLatex(Substitution sub) {
return new StringBuilder(BRACKET_LEFT)
.append(AMPERSAND)
.append(new LatexCreatorType(sub.getVariable(), mode).getLatex())
.append(SUBSTITUTION_SIGN)
.append(new LatexCreatorType(sub.getType(), mode).getLatex())
.append(BRACKET_RIGHT)
.append(LATEX_NEW_LINE).toString();
}
private void createUnficationTexts() {
List<UnificationStep> unificationSteps = typeInferer.getUnificationSteps()
.orElseThrow(IllegalStateException::new);
List<Constraint> initialConstraints = unificationSteps.get(0).getConstraints();
// skip first step since the substitutions list is still empty (unification introduction is shown)
Constraint currentConstraint = initialConstraints.get(initialConstraints.size() - 1);
for (int stepNum = 1; stepNum < unificationSteps.size() - 1; stepNum++) {
UnificationStep step = unificationSteps.get(stepNum);
Result<List<Substitution>, UnificationError> subs = step.getSubstitutions();
if (subs.isError()) {
createErrorText(subs.unwrapError());
errorOccurred = true;
break;
}
List<Constraint> constraints = step.getConstraints();
Queue<Type> leftTypeArgs = typeDeterminer.getArguments(currentConstraint.getFirstType());
Queue<Type> rightTypeArgs = typeDeterminer.getArguments(currentConstraint.getSecondType());
if (leftTypeArgs.isEmpty()) {
// left side is a variable
createVariableText(currentConstraint.getFirstType(), currentConstraint.getSecondType(),
currentConstraint, subs.unwrap().get(0));
} else if (rightTypeArgs.isEmpty()) {
// right side is a variable
createVariableText(currentConstraint.getSecondType(), currentConstraint.getFirstType(),
currentConstraint, subs.unwrap().get(0));
} else {
// both sides are functions
createFunctionText(leftTypeArgs, rightTypeArgs, currentConstraint,
constraints.get(constraints.size() - 1), constraints.get(constraints.size() - 2));
}
currentConstraint = constraints.get(constraints.size() - 1);
}
}
private void createFunctionText(Queue<Type> leftTypeArgs, Queue<Type> rightTypeArgs, Constraint currentConstraint,
Constraint newConstraint1, Constraint newConstraint2) {
StringBuilder latex = new StringBuilder();
latex.append(getDefaultTextLatex("key")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(currentConstraint, mode))).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(currentConstraint.getFirstType(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(currentConstraint.getSecondType(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(leftTypeArgs.poll(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(rightTypeArgs.poll(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(leftTypeArgs.poll(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(rightTypeArgs.poll(), mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(currentConstraint, mode))).
append(getDefaultTextLatex("key")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(newConstraint1, mode))).
append(getDefaultTextLatex("key")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(newConstraint2, mode))).
append(getDefaultTextLatex("key")).toString();
unificationTexts.add(latex.toString());
}
private void createVariableText(Type variable, Type anyType, Constraint currentConstraint,
Substitution newSubstitution) {
StringBuilder latex = new StringBuilder();
latex.append(getDefaultTextLatex("key")).
append(toLatex(LatexCreatorConstraints.createSingleConstraint(currentConstraint, mode))).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(variable, mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(variable, mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(new LatexCreatorType(anyType, mode).getLatex())).
append(getDefaultTextLatex("key")).
append(toLatex(getSubstitutionLatex(newSubstitution))).
append(getDefaultTextLatex("key"));
unificationTexts.add(latex.toString());
}
private void createErrorText(UnificationError errorType) {
if (errorType == UnificationError.DIFFERENT_TYPES) {
unificationTexts.add(getDefaultTextLatex("key"));
} else if (errorType == UnificationError.INFINITE_TYPE) {
unificationTexts.add(getDefaultTextLatex("key"));
}
}
}