transcendental-lisp/src/main/kotlin/function/builtin/predicate/GENSYM_EQUAL.java
2018-03-23 18:12:47 -04:00

101 lines
3.0 KiB
Java

package function.builtin.predicate;
import function.ArgumentValidator;
import function.FunctionNames;
import function.LispFunction;
import sexpression.Cons;
import sexpression.SExpression;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static function.builtin.GENSYM.GENSYM_PREFIX;
import static sexpression.Nil.NIL;
import static sexpression.Symbol.T;
@FunctionNames({ "GENSYM-EQUAL", "GENSYM-EQUAL?" })
public class GENSYM_EQUAL extends LispFunction {
private ArgumentValidator argumentValidator;
public GENSYM_EQUAL(String name) {
this.argumentValidator = new ArgumentValidator(name);
this.argumentValidator.setExactNumberOfArguments(2);
}
@Override
public SExpression call(Cons argumentList) {
argumentValidator.validate(argumentList);
Cons rest = (Cons) argumentList.getRest();
SExpression firstArgument = argumentList.getFirst();
SExpression secondArgument = rest.getFirst();
return gensymEqual(firstArgument, secondArgument);
}
private SExpression gensymEqual(SExpression firstArgument, SExpression secondArgument) {
String firstEqualized = equalizeGensyms(firstArgument);
String secondEqualized = equalizeGensyms(secondArgument);
return firstEqualized.equals(secondEqualized) ? T : NIL;
}
private String equalizeGensyms(SExpression expression) {
GensymEqualizer equalizer = new GensymEqualizer(expression.toString());
return equalizer.equalize();
}
private static class GensymEqualizer {
private static final String GENSYM_REGEX = Pattern.quote(GENSYM_PREFIX) + "[0-9]+";
Map<String, String> gensymAliases;
Matcher matcher;
String expression;
int counter;
public GensymEqualizer(String expression) {
this.gensymAliases = new HashMap<>();
this.matcher = Pattern.compile(GENSYM_REGEX).matcher(expression);
this.expression = expression;
this.counter = 0;
}
public String equalize() {
createGensymAliases();
return equalizeGensyms();
}
private void createGensymAliases() {
while (matcher.find())
createAliasForGensym();
}
private void createAliasForGensym() {
String gensym = matcher.group();
if (isNewGensym(gensym))
gensymAliases.put(gensym, GENSYM_PREFIX + (counter++));
}
private boolean isNewGensym(String gensym) {
return !gensymAliases.containsKey(gensym);
}
private String equalizeGensyms() {
String equalizedExpression = expression;
for (Entry<String, String> entry : gensymAliases.entrySet())
equalizedExpression = equalizedExpression.replace(entry.getKey(), entry.getValue());
return equalizedExpression;
}
}
}