From 7ef304d90151985ea9b1aa5569fba99c42350040 Mon Sep 17 00:00:00 2001 From: Kamila Szewczyk Date: Sat, 12 Nov 2022 23:43:59 +0100 Subject: [PATCH] spaceship operator. 10'000 lines of code! --- .../kamilalisp/runtime/FunctionRegistry.java | 4 +- .../kamilalisp/runtime/math/cmp/Neq.java | 2 +- .../runtime/math/cmp/Spaceship.java | 45 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Spaceship.java diff --git a/src/main/java/palaiologos/kamilalisp/runtime/FunctionRegistry.java b/src/main/java/palaiologos/kamilalisp/runtime/FunctionRegistry.java index bea592e31..4e43a43b5 100644 --- a/src/main/java/palaiologos/kamilalisp/runtime/FunctionRegistry.java +++ b/src/main/java/palaiologos/kamilalisp/runtime/FunctionRegistry.java @@ -41,7 +41,7 @@ public class FunctionRegistry { "n-prod", "Π", "unique-mask", "unique", "intersection", "union", "bernoulli", "regex-matches?", "date:from", "date:time-from", "date:add", "date:difference", "date:hours", "date:minutes", "date:seconds", "date:nanoseconds", "date:years", "date:months", - "date:days", "date:to-list", "time:day-of-week", "⍣" + "date:days", "date:to-list", "time:day-of-week", "⍣", "<=>", "⇔" ); public static void registerDefault(Environment env) { @@ -207,6 +207,8 @@ public static void registerDefault(Environment env) { env.set("*", new Atom(new Star())); env.set("/", new Atom(new Slash())); env.set("mod", new Atom(new Mod())); + env.set("<=>", new Atom(new Spaceship())); + env.set("⇔", new Atom(new Spaceship())); env.set("regex:matches?", new Atom(new RegexMatches())); diff --git a/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Neq.java b/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Neq.java index 59d9a9af7..01a61f7c9 100644 --- a/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Neq.java +++ b/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Neq.java @@ -7,7 +7,7 @@ import java.util.List; public class Neq extends PrimitiveFunction implements Lambda { - private static final String name = "!="; + private static final String name = "/="; @Override protected String name() { diff --git a/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Spaceship.java b/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Spaceship.java new file mode 100644 index 000000000..55ae7460a --- /dev/null +++ b/src/main/java/palaiologos/kamilalisp/runtime/math/cmp/Spaceship.java @@ -0,0 +1,45 @@ +package palaiologos.kamilalisp.runtime.math.cmp; + +import com.google.common.collect.Streams; +import palaiologos.kamilalisp.atom.*; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.List; + +public class Spaceship extends PrimitiveFunction implements Lambda { + private static final String name = "<=>"; + + @Override + protected String name() { + return name; + } + + private static Atom cmp2(Environment e, Atom a, Atom b) { + if (a.getType() == Type.REAL && b.getType() == Type.REAL) { + return new Atom(BigInteger.valueOf(a.getReal().compareTo(b.getReal()))); + } else if (a.getType() == Type.REAL && b.getType() == Type.INTEGER) { + return new Atom(BigInteger.valueOf(a.getReal().compareTo(new BigDecimal(b.getInteger())))); + } else if (a.getType() == Type.INTEGER && b.getType() == Type.REAL) { + return new Atom(BigInteger.valueOf(new BigDecimal(a.getInteger()).compareTo(b.getReal()))); + } else if (a.getType() == Type.INTEGER && b.getType() == Type.INTEGER) { + return new Atom(BigInteger.valueOf(a.getInteger().compareTo(b.getInteger()))); + } else if (a.getType() == Type.STRING && b.getType() == Type.STRING) { + return new Atom(BigInteger.valueOf(a.getString().compareTo(b.getString()))); + } else if (a.getType() == Type.LIST && (b.getType() == Type.REAL || b.getType() == Type.INTEGER || b.getType() == Type.STRING)) { + return new Atom(a.getList().stream().map(x -> cmp2(e, x, b)).toList()); + } else if ((a.getType() == Type.REAL || a.getType() == Type.INTEGER || a.getType() == Type.STRING) && b.getType() == Type.LIST) { + return new Atom(b.getList().stream().map(x -> cmp2(e, a, x)).toList()); + } else if (a.getType() == Type.LIST && b.getType() == Type.LIST) { + return new Atom(Streams.zip(a.getList().stream(), b.getList().stream(), (x, y) -> cmp2(e, x, y)).toList()); + } else { + throw new UnsupportedOperationException(name + " not defined for: " + a.getType() + " and " + b.getType()); + } + } + + @Override + public Atom apply(Environment env, List args) { + assertArity(args, 2); + return cmp2(env, args.get(0), args.get(1)); + } +}