Compare commits

..

4 Commits

15 changed files with 172 additions and 68 deletions

View File

@ -17,6 +17,7 @@ import me.topchetoeu.j2s.common.Instruction.BreakpointType;
public class FunctionMap { public class FunctionMap {
public static class FunctionMapBuilder { public static class FunctionMapBuilder {
private Location first, last;
private final TreeMap<Integer, Location> sourceMap = new TreeMap<>(); private final TreeMap<Integer, Location> sourceMap = new TreeMap<>();
private final HashMap<Location, BreakpointType> breakpoints = new HashMap<>(); private final HashMap<Location, BreakpointType> breakpoints = new HashMap<>();
@ -31,6 +32,9 @@ public class FunctionMap {
} }
public FunctionMapBuilder setLocation(int i, Location loc) { public FunctionMapBuilder setLocation(int i, Location loc) {
if (loc == null || i < 0) return this; 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); sourceMap.put(i, loc);
return this; return this;
} }
@ -41,12 +45,10 @@ public class FunctionMap {
} }
public Location first() { public Location first() {
if (sourceMap.size() == 0) return null; return first;
return sourceMap.firstEntry().getValue();
} }
public Location last() { public Location last() {
if (sourceMap.size() == 0) return null; return last;
return sourceMap.lastEntry().getValue();
} }
public FunctionMapBuilder map(Function<Location, Location> mapper) { public FunctionMapBuilder map(Function<Location, Location> mapper) {
@ -74,10 +76,10 @@ public class FunctionMap {
} }
public FunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) { 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<Location, Location> mapper) { public FunctionMap build() {
return new FunctionMap(sourceMap, breakpoints, new String[0], new String[0], new String[0]); return new FunctionMap(sourceMap, breakpoints, first, last, new String[0], new String[0], new String[0]);
} }
private FunctionMapBuilder() { } private FunctionMapBuilder() { }
@ -91,11 +93,12 @@ public class FunctionMap {
private final TreeMap<Integer, Location> pcToLoc = new TreeMap<>(); private final TreeMap<Integer, Location> pcToLoc = new TreeMap<>();
public final String[] localNames, capturableNames, captureNames; 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; if (pcToLoc.size() == 0 || pc < 0 || pc > pcToLoc.lastKey()) return null;
var res = pcToLoc.get(pc); var res = pcToLoc.get(pc);
if (!approxiamte || res != null) return res; if (!approximate || res != null) return res;
var entry = pcToLoc.headMap(pc, true).lastEntry(); var entry = pcToLoc.headMap(pc, true).lastEntry();
if (entry == null) return null; if (entry == null) return null;
else return entry.getValue(); else return entry.getValue();
@ -151,7 +154,7 @@ public class FunctionMap {
} }
public FunctionMap clone() { 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.pcToLoc.putAll(this.pcToLoc);
res.bps.putAll(bps); res.bps.putAll(bps);
res.bpLocs.putAll(bpLocs); res.bpLocs.putAll(bpLocs);
@ -159,7 +162,7 @@ public class FunctionMap {
return res; return res;
} }
public FunctionMap(Map<Integer, Location> map, Map<Location, BreakpointType> breakpoints, String[] localNames, String[] capturableNames, String[] captureNames) { public FunctionMap(Map<Integer, Location> map, Map<Location, BreakpointType> breakpoints, Location first, Location last, String[] localNames, String[] capturableNames, String[] captureNames) {
var locToPc = new HashMap<Location, Integer>(); var locToPc = new HashMap<Location, Integer>();
for (var el : map.entrySet()) { for (var el : map.entrySet()) {
@ -178,11 +181,16 @@ public class FunctionMap {
this.localNames = localNames; this.localNames = localNames;
this.captureNames = captureNames; this.captureNames = captureNames;
this.capturableNames = capturableNames; this.capturableNames = capturableNames;
this.first = first;
this.last = last;
} }
private FunctionMap() { private FunctionMap() {
localNames = new String[0]; localNames = new String[0];
captureNames = new String[0]; captureNames = new String[0];
capturableNames = new String[0]; capturableNames = new String[0];
first = null;
last = null;
} }
public static FunctionMapBuilder builder() { public static FunctionMapBuilder builder() {

View File

@ -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<String> FOO = new Key<>();
private final Key<Void> 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));
}
}

View File

@ -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());
}
}

View File

@ -1,14 +0,0 @@
package me.topchetoeu.j2s;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestHelloWorld {
@Test
public void testHelloWorld() {
final String message = "Hello World!";
assertEquals("Hello World!", message);
}
}

View File

@ -26,6 +26,10 @@ import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.json.JSON; import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.parsing.Parsing; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.repl.buffers.Int32ArrayValue;
import me.topchetoeu.j2s.repl.buffers.Int8ArrayValue;
import me.topchetoeu.j2s.repl.buffers.TypedArrayValue;
import me.topchetoeu.j2s.repl.buffers.Uint8ArrayValue;
import me.topchetoeu.j2s.repl.debug.DebugServer; import me.topchetoeu.j2s.repl.debug.DebugServer;
import me.topchetoeu.j2s.repl.debug.Debugger; import me.topchetoeu.j2s.repl.debug.Debugger;
import me.topchetoeu.j2s.repl.debug.SimpleDebugger; import me.topchetoeu.j2s.repl.debug.SimpleDebugger;
@ -44,10 +48,6 @@ import me.topchetoeu.j2s.runtime.values.functions.NativeFunction;
import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue; import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue;
import me.topchetoeu.j2s.runtime.values.objects.ArrayValue; import me.topchetoeu.j2s.runtime.values.objects.ArrayValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.objects.buffers.Int32ArrayValue;
import me.topchetoeu.j2s.runtime.values.objects.buffers.Int8ArrayValue;
import me.topchetoeu.j2s.runtime.values.objects.buffers.TypedArrayValue;
import me.topchetoeu.j2s.runtime.values.objects.buffers.Uint8ArrayValue;
import me.topchetoeu.j2s.runtime.values.primitives.BoolValue; import me.topchetoeu.j2s.runtime.values.primitives.BoolValue;
import me.topchetoeu.j2s.runtime.values.primitives.StringValue; import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue; import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue;
@ -701,7 +701,7 @@ public class SimpleRepl {
res.defineOwnField(env, "invoke", new NativeFunction(args -> { res.defineOwnField(env, "invoke", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0); var func = (FunctionValue)args.get(0);
var self = args.get(1); var self = args.get(1);
var funcArgs = (ArrayValue)args.get(2); var funcArgs = (ArrayLikeValue)args.get(2);
return func.apply(env, self, funcArgs.toArray()); return func.apply(env, self, funcArgs.toArray());
})); }));

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.runtime.values.objects.buffers; package me.topchetoeu.j2s.repl.buffers;
public final class Int32ArrayValue extends TypedArrayValue { public final class Int32ArrayValue extends TypedArrayValue {
@Override protected int onGet(int i) { @Override protected int onGet(int i) {

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.runtime.values.objects.buffers; package me.topchetoeu.j2s.repl.buffers;
public final class Int8ArrayValue extends TypedArrayValue { public final class Int8ArrayValue extends TypedArrayValue {
@Override protected int onGet(int i) { @Override protected int onGet(int i) {

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.runtime.values.objects.buffers; package me.topchetoeu.j2s.repl.buffers;
import java.util.WeakHashMap; import java.util.WeakHashMap;

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.runtime.values.objects.buffers; package me.topchetoeu.j2s.repl.buffers;
public final class Uint8ArrayValue extends TypedArrayValue { public final class Uint8ArrayValue extends TypedArrayValue {
@Override protected int onGet(int i) { @Override protected int onGet(int i) {

View File

@ -1,14 +0,0 @@
package me.topchetoeu.j2s;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestHelloWorld {
@Test
public void testHelloWorld() {
final String message = "Hello World!";
assertEquals("Hello World!", message);
}
}

View File

@ -1,13 +1,53 @@
package me.topchetoeu.j2s.runtime; package me.topchetoeu.j2s.runtime;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.values.Value; import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ArrayValue; import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue;
public class ArgumentsValue extends ArrayValue { public class ArgumentsValue extends ArrayLikeValue {
public final Frame frame; public final Frame frame;
private Value[] args;
private boolean shadowed;
public ArgumentsValue(Frame frame, Value... args) { private void shadow() {
super(args); if (!shadowed) {
var newArgs = new Value[args.length];
System.arraycopy(args, 0, newArgs, 0, args.length);
args = newArgs;
shadowed = true;
}
}
@Override public Value get(int i) {
return args[i];
}
@Override public boolean has(int i) {
if (i < 0 || i >= size()) return false;
if (shadowed) return args[i] != null;
else return true;
}
@Override public boolean remove(int i) {
shadow();
args[i] = null;
return true;
}
@Override public boolean set(Environment env, int i, Value val) {
shadow();
args[i] = val;
return true;
}
@Override public boolean setSize(int val) {
return false;
}
@Override public int size() {
return args.length;
}
public ArgumentsValue(Frame frame) {
this.frame = frame; this.frame = frame;
this.args = frame.args;
this.shadowed = false;
setPrototype(e -> null);
} }
} }

View File

@ -383,7 +383,7 @@ public final class Frame {
this.self = self; this.self = self;
this.args = args; this.args = args;
this.argsVal = new ArgumentsValue(this, args); this.argsVal = new ArgumentsValue(this);
this.argsLen = new IntValue(args.length); this.argsLen = new IntValue(args.length);
this.captures = func.captures; this.captures = func.captures;

View File

@ -56,6 +56,17 @@ public abstract class ArrayLikeValue extends ObjectValue {
public abstract boolean has(int i); public abstract boolean has(int i);
public abstract boolean remove(int i); public abstract boolean remove(int i);
public Value[] toArray() {
var n = size();
var res = new Value[n];
for (var i = 0; i < n; i++) {
if (has(i)) res[i] = get(i);
}
return res;
}
@Override public Member getOwnMember(Environment env, KeyCache key) { @Override public Member getOwnMember(Environment env, KeyCache key) {
var res = super.getOwnMember(env, key); var res = super.getOwnMember(env, key);
if (res != null) return res; if (res != null) return res;

View File

@ -68,7 +68,7 @@ public class ArrayValue extends ArrayLikeValue implements Iterable<Value> {
} }
} }
public Value[] toArray() { @Override public Value[] toArray() {
var res = new Value[size]; var res = new Value[size];
copyTo(res, 0, 0, size); copyTo(res, 0, 0, size);
return res; return res;

View File

@ -1,14 +0,0 @@
package me.topchetoeu.j2s;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestHelloWorld {
@Test
public void testHelloWorld() {
final String message = "Hello World!";
assertEquals("Hello World!", message);
}
}