diff --git a/common/src/main/java/me/topchetoeu/j2s/common/FunctionMap.java b/common/src/main/java/me/topchetoeu/j2s/common/FunctionMap.java index 2e8cd02..cb39a5c 100644 --- a/common/src/main/java/me/topchetoeu/j2s/common/FunctionMap.java +++ b/common/src/main/java/me/topchetoeu/j2s/common/FunctionMap.java @@ -17,6 +17,7 @@ import me.topchetoeu.j2s.common.Instruction.BreakpointType; public class FunctionMap { public static class FunctionMapBuilder { + private Location first, last; private final TreeMap sourceMap = new TreeMap<>(); private final HashMap breakpoints = new HashMap<>(); @@ -31,6 +32,9 @@ public class FunctionMap { } public FunctionMapBuilder setLocation(int i, Location loc) { if (loc == null || i < 0) return this; + if (first == null || first.compareTo(loc) > 0) first = loc; + if (last == null || last.compareTo(loc) < 0) last = loc; + sourceMap.put(i, loc); return this; } @@ -41,12 +45,10 @@ public class FunctionMap { } public Location first() { - if (sourceMap.size() == 0) return null; - return sourceMap.firstEntry().getValue(); + return first; } public Location last() { - if (sourceMap.size() == 0) return null; - return sourceMap.lastEntry().getValue(); + return last; } public FunctionMapBuilder map(Function mapper) { @@ -74,10 +76,10 @@ public class FunctionMap { } public FunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) { - return new FunctionMap(sourceMap, breakpoints, localNames, capturableNames, captureNames); + return new FunctionMap(sourceMap, breakpoints, first, last, localNames, capturableNames, captureNames); } - public FunctionMap build(Function mapper) { - return new FunctionMap(sourceMap, breakpoints, new String[0], new String[0], new String[0]); + public FunctionMap build() { + return new FunctionMap(sourceMap, breakpoints, first, last, new String[0], new String[0], new String[0]); } private FunctionMapBuilder() { } @@ -91,11 +93,12 @@ public class FunctionMap { private final TreeMap pcToLoc = new TreeMap<>(); public final String[] localNames, capturableNames, captureNames; + public final Location first, last; - public Location toLocation(int pc, boolean approxiamte) { + public Location toLocation(int pc, boolean approximate) { if (pcToLoc.size() == 0 || pc < 0 || pc > pcToLoc.lastKey()) return null; var res = pcToLoc.get(pc); - if (!approxiamte || res != null) return res; + if (!approximate || res != null) return res; var entry = pcToLoc.headMap(pc, true).lastEntry(); if (entry == null) return null; else return entry.getValue(); @@ -151,7 +154,7 @@ public class FunctionMap { } public FunctionMap clone() { - var res = new FunctionMap(new HashMap<>(), new HashMap<>(), localNames, capturableNames, captureNames); + var res = new FunctionMap(new HashMap<>(), new HashMap<>(), first, last, localNames, capturableNames, captureNames); res.pcToLoc.putAll(this.pcToLoc); res.bps.putAll(bps); res.bpLocs.putAll(bpLocs); @@ -159,7 +162,7 @@ public class FunctionMap { return res; } - public FunctionMap(Map map, Map breakpoints, String[] localNames, String[] capturableNames, String[] captureNames) { + public FunctionMap(Map map, Map breakpoints, Location first, Location last, String[] localNames, String[] capturableNames, String[] captureNames) { var locToPc = new HashMap(); for (var el : map.entrySet()) { @@ -178,11 +181,16 @@ public class FunctionMap { this.localNames = localNames; this.captureNames = captureNames; this.capturableNames = capturableNames; + + this.first = first; + this.last = last; } private FunctionMap() { localNames = new String[0]; captureNames = new String[0]; capturableNames = new String[0]; + first = null; + last = null; } public static FunctionMapBuilder builder() { diff --git a/common/src/test/java/me/topchetoeu/j2s/common/TestEnvironment.java b/common/src/test/java/me/topchetoeu/j2s/common/TestEnvironment.java new file mode 100644 index 0000000..0aa0354 --- /dev/null +++ b/common/src/test/java/me/topchetoeu/j2s/common/TestEnvironment.java @@ -0,0 +1,69 @@ +package me.topchetoeu.j2s.common; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import org.junit.jupiter.api.Test; + +public class TestEnvironment { + private final Key FOO = new Key<>(); + private final Key MARKER = new Key<>(); + + @Test public void testShouldCreate() { + new Environment(); + Environment.empty(); + } + @Test public void testShouldNotExist() { + var env = new Environment(); + assertEquals(null, env.get(FOO)); + assertEquals(false, env.has(FOO)); + } + + @Test public void testShouldAdd() { + var env = new Environment(); + env.add(FOO, "test"); + assertEquals("test", env.get(FOO)); + } + + @Test public void testShouldGetFromParent() { + var parent = new Environment(); + parent.add(FOO, "test"); + var child = parent.child(); + assertEquals("test", child.get(FOO)); + assertEquals(true, child.has(FOO)); + } + @Test public void testShouldHideParent() { + var parent = new Environment(); + parent.add(FOO, "test"); + var child = parent.child(); + child.remove(FOO); + assertEquals(null, child.get(FOO)); + assertEquals(false, child.has(FOO)); + } + + @Test public void testShouldAddMarker() { + var env = new Environment(); + env.add(MARKER); + assertEquals(true, env.has(MARKER)); + assertEquals(false, env.hasNotNull(MARKER)); + } + + @Test public void testShouldInitOnce() { + var env = new Environment(); + assertEquals("a", env.init(FOO, "a")); + assertEquals("a", env.init(FOO, "b")); + assertEquals("a", env.get(FOO)); + } + @Test public void testShouldInitOnceFrom() { + var env = new Environment(); + assertEquals("a", env.initFrom(FOO, () -> "a")); + assertEquals("a", env.initFrom(FOO, () -> "b")); + assertEquals("a", env.get(FOO)); + } + + @Test public void testShouldWrap() { + var env = new Environment(); + assertEquals(env, Environment.wrap(env)); + assertInstanceOf(Environment.class, Environment.wrap(null)); + } +} diff --git a/common/src/test/java/me/topchetoeu/j2s/common/TestFunctionMap.java b/common/src/test/java/me/topchetoeu/j2s/common/TestFunctionMap.java new file mode 100644 index 0000000..f3ac0e4 --- /dev/null +++ b/common/src/test/java/me/topchetoeu/j2s/common/TestFunctionMap.java @@ -0,0 +1,18 @@ +package me.topchetoeu.j2s.common; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +public class TestFunctionMap { + @Test public void createEmpty() { + FunctionMap.builder().build(null, null, null); + FunctionMap.builder().build(); + } + @Test public void startOfEmpty() { + var empty = FunctionMap.EMPTY; + + assertEquals(null, empty.start()); + assertEquals(null, empty.end()); + } +}