From 62ed37ffdd0d6c892c3f359b9d837a011bace81f Mon Sep 17 00:00:00 2001 From: NPException Date: Mon, 12 Nov 2018 22:29:01 +0100 Subject: [PATCH] fix read and eval of Lists, Sets, and Maps --- .../npecomplete/mc/testproject/lisp/Lisp.java | 40 +++++++++++++++++++ .../mc/testproject/lisp/util/LispReader.java | 11 ++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/npecomplete/mc/testproject/lisp/Lisp.java b/src/main/java/de/npecomplete/mc/testproject/lisp/Lisp.java index c1c40e0..26a04bc 100644 --- a/src/main/java/de/npecomplete/mc/testproject/lisp/Lisp.java +++ b/src/main/java/de/npecomplete/mc/testproject/lisp/Lisp.java @@ -1,7 +1,12 @@ package de.npecomplete.mc.testproject.lisp; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; import de.npecomplete.mc.testproject.lisp.data.Sequence; import de.npecomplete.mc.testproject.lisp.data.Symbol; @@ -95,6 +100,41 @@ public static Object eval(Object obj, Environment env) throws LispException { + "Call: " + call); } + if (obj instanceof List) { + List list = (List) obj; + List result = new ArrayList<>(); + for (Object o : list) { + result.add(eval(o, env)); + } + return result; + } + + if (obj instanceof Set) { + Set set = (Set) obj; + Set result = new HashSet<>(set.size() * 2); + for (Object o : set) { + Object key = eval(o, env); + if (result.contains(key)) { + throw new LispException("Set creation with duplicate key: " + key); + } + result.add(key); + } + return result; + } + + if (obj instanceof Map) { + Map map = (Map) obj; + Map result = new HashMap<>(map.size() * 2); + for (Entry e : map.entrySet()) { + Object key = eval(e.getKey(), env); + if (result.containsKey(key)) { + throw new LispException("Map creation with duplicate key: " + key); + } + result.put(key, eval(e.getValue(), env)); + } + return result; + } + return obj; } } diff --git a/src/main/java/de/npecomplete/mc/testproject/lisp/util/LispReader.java b/src/main/java/de/npecomplete/mc/testproject/lisp/util/LispReader.java index a4cf1a6..aee2804 100644 --- a/src/main/java/de/npecomplete/mc/testproject/lisp/util/LispReader.java +++ b/src/main/java/de/npecomplete/mc/testproject/lisp/util/LispReader.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.stream.IntStream; import de.npecomplete.mc.testproject.lisp.LispException; @@ -125,7 +126,9 @@ private static void buildCollection(Collection base, Token end, Iterator if (value == end) { return; } - base.add(value); + if (!base.add(value) && base instanceof Set) { + throw new LispException("Duplicate key in set literal: " + value); + } } throw new LispException("Encountered end of data while reading a collection"); } @@ -139,7 +142,11 @@ private static Object buildMap(Iterator it) { Map map = new HashMap<>(mapContents.size()); Iterator mapIt = mapContents.iterator(); while (mapIt.hasNext()) { - map.put(mapIt.next(), mapIt.next()); + Object key = mapIt.next(); + if (map.containsKey(key)) { + throw new LispException("Duplicate key in map literal: " + key); + } + map.put(key, mapIt.next()); } return Collections.unmodifiableMap(map); }