Merge pull request 'Write some tests' (#33) from topchetoeu/tests into master

Reviewed-on: #33
This commit is contained in:
TopchetoEU 2025-01-15 18:23:24 +00:00
commit 01e86b5e70
127 changed files with 1168 additions and 472 deletions

View File

@ -45,8 +45,8 @@ env.add(Compiler.KEY, (_env, filename, raw, mapper) -> {
// We'll register the source and function source mappings for debugging
DebugContext.get(env).onSource(filename, raw);
for (var el : res.bodies()) {
DebugContext.get(env).onFunctionLoad(el, res.map(mapper));
for (var el : res.all()) {
DebugContext.get(env).onFunctionLoad(el.body(), el.map(mapper));
}
// Finally, we will construct the function

View File

@ -5,7 +5,7 @@ plugins {
description = "A collection of utils and structures for the rest of the project";
tasks.processResources {
filesMatching("metadata.json", {
filesMatching("metadata", {
expand(
"version" to properties["project_version"],
"name" to properties["project_name"],

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.environment;
package me.topchetoeu.j2s.common;
import java.util.HashMap;
import java.util.HashSet;
@ -63,8 +63,11 @@ public class Environment {
}
public <T> T init(Key<T> key, T val) {
if (!has(key)) this.add(key, val);
return val;
if (!has(key)) {
this.add(key, val);
return val;
}
else return get(key);
}
public <T> T initFrom(Key<T> key, Supplier<T> val) {
if (!has(key)) {

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.common;
import java.io.File;

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.mapping;
package me.topchetoeu.j2s.common;
import java.util.ArrayList;
import java.util.Arrays;
@ -14,11 +14,10 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.Location;
public class FunctionMap {
public static class FunctionMapBuilder {
private Location first, last;
private final TreeMap<Integer, Location> sourceMap = new TreeMap<>();
private final HashMap<Location, BreakpointType> breakpoints = new HashMap<>();
@ -33,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;
}
@ -43,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<Location, Location> mapper) {
@ -76,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<Location, Location> 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() { }
@ -93,11 +93,12 @@ public class FunctionMap {
private final TreeMap<Integer, Location> 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();
@ -153,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);
@ -161,7 +162,7 @@ public class FunctionMap {
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>();
for (var el : map.entrySet()) {
@ -180,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() {

View File

@ -4,8 +4,6 @@ import java.util.HashMap;
import java.util.function.IntFunction;
import java.util.function.IntSupplier;
import me.topchetoeu.j2s.common.parsing.Location;
public class Instruction {
public static enum Type {
RETURN(0x00),

View File

@ -0,0 +1,3 @@
package me.topchetoeu.j2s.common;
public final class Key<T> { }

View File

@ -1,10 +1,8 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.common;
import java.util.ArrayList;
import java.util.Objects;
import me.topchetoeu.j2s.common.Metadata;
public abstract class Location implements Comparable<Location> {
public static final Location INTERNAL = Location.of(new Filename(Metadata.name(), "native"), -1, -1);
@ -32,9 +30,9 @@ public abstract class Location implements Comparable<Location> {
};
}
public final Location nextLine() {
return changeLine(1);
return nextLine(1);
}
public final Location changeLine(int offset) {
public final Location nextLine(int offset) {
var self = this;
return new Location() {
@ -60,7 +58,14 @@ public abstract class Location implements Comparable<Location> {
}
@Override public int compareTo(Location other) {
int a = filename().toString().compareTo(other.filename().toString());
int a;
var filenameA = filename();
var filenameB = other.filename();
if (filenameB == null && filenameA == null) a = 0;
else if (filenameA == null) a = -1;
else if (filenameB == null) a = 1;
else a = filenameA.toString().compareTo(filenameB.toString());
int b = Integer.compare(line(), other.line());
int c = Integer.compare(start(), other.start());
@ -79,21 +84,27 @@ public abstract class Location implements Comparable<Location> {
}
public static Location of(String raw) {
var i0 = raw.lastIndexOf(':');
if (i0 < 0) return Location.of(Filename.parse(raw), -1, -1);
var i1 = raw.lastIndexOf(':');
if (i1 < 0) return Location.of(Filename.parse(raw), -1, -1);
var i1 = raw.lastIndexOf(':', i0);
var i0 = raw.substring(0, i1).lastIndexOf(':', i1);
if (i0 < 0) {
try {
return Location.of(Filename.parse(raw.substring(0, i0)), Integer.parseInt(raw.substring(i0 + 1)), -1);
return Location.of(null, Integer.parseInt(raw.substring(0, i1)) - 1, Integer.parseInt(raw.substring(i1 + 1)) - 1);
}
catch (NumberFormatException e) {
return Location.of(Filename.parse(raw), -1, -1);
catch (NumberFormatException e) {}
try {
return Location.of(Filename.parse(raw.substring(0, i1)), Integer.parseInt(raw.substring(i1 + 1)) - 1, -1);
}
catch (NumberFormatException e) {}
return Location.of(Filename.parse(raw), -1, -1);
}
int start, line;
try {
start = Integer.parseInt(raw.substring(i1 + 1));
}
@ -105,9 +116,9 @@ public abstract class Location implements Comparable<Location> {
line = Integer.parseInt(raw.substring(i0 + 1, i1));
}
catch (NumberFormatException e) {
return Location.of(Filename.parse(raw.substring(i1 + 1)), start, -1);
return Location.of(Filename.parse(raw.substring(0, i1)), start - 1, -1);
}
return Location.of(Filename.parse(raw.substring(0, i0)), start, line);
return Location.of(Filename.parse(raw.substring(0, i0)), line - 1, start - 1);
}
}

View File

@ -1,18 +1,46 @@
package me.topchetoeu.j2s.common;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.parsing.Filename;
public class Metadata {
private static final String VERSION;
private static final String AUTHOR;
private static final String NAME;
private static String VERSION;
private static String AUTHOR;
private static String NAME;
static {
var data = JSON.parse(new Filename("internal", "metadata.json"), Reading.resourceToString("metadata.json")).map();
VERSION = data.string("version");
AUTHOR = data.string("author");
NAME = data.string("name");
var raw = Reading.resourceToString("metadata").split("\n");
var line = 0;
var file = "internal://metadata";
for (var el : raw) {
line++;
el = el.trim();
if (el.startsWith("#")) continue;
if (el.isEmpty()) continue;
var i = el.indexOf(":");
if (i < 0) throw new RuntimeException(String.format("%s:%s: Expected colon on line", file, line));
var name = el.substring(0, i).trim();
var value = el.substring(i + 1).trim();
switch (name) {
case "version":
VERSION = value;
break;
case "author":
AUTHOR = value;
break;
case "name":
NAME = name;
break;
default:
throw new RuntimeException(String.format("%s:%s: Unexpected metadata key '%s'", file, line, name));
}
}
if (VERSION == null) throw new RuntimeException(String.format("%s:%s: No version specified", file, line));
if (AUTHOR == null) throw new RuntimeException(String.format("%s:%s: No author specified", file, line));
if (NAME == null) throw new RuntimeException(String.format("%s:%s: No name specified", file, line));
}
public static String version() {

View File

@ -0,0 +1,123 @@
package me.topchetoeu.j2s.common;
import java.math.BigDecimal;
public class StringifyUtils {
public static String quoteString(String raw) {
var res = new StringBuilder("\"");
var alphabet = "0123456789ABCDEF".toCharArray();
for (var c : raw.toCharArray()) {
if (c < 32 || c >= 127) {
res
.append("\\u")
.append(alphabet[(c >> 12) & 0xF])
.append(alphabet[(c >> 8) & 0xF])
.append(alphabet[(c >> 4) & 0xF])
.append(alphabet[(c >> 0) & 0xF]);
}
else if (c == '\\')
res.append("\\\\");
else if (c == '"')
res.append("\\\"");
else res.append(c);
}
return res.append('"').toString();
}
public static String quoteNumber(Double num) {
if (num == Double.NEGATIVE_INFINITY) return "-Infinity";
if (num == Double.POSITIVE_INFINITY) return "Infinity";
if (Double.isNaN(num)) return "NaN";
return BigDecimal.valueOf(num).stripTrailingZeros().toPlainString();
}
private static double power(double a, long b) {
if (b == 0) return 1;
if (b == 1) return a;
if (b < 0) return 1 / power(a, -b);
if ((b & 1) == 0) return power(a * a, b / 2);
else return a * power(a * a, b / 2);
}
public static Double unqoteNumber(String src) {
var i = 0;
double whole = 0;
double fract = 0;
long exponent = 0;
boolean parsedAny = false;
boolean negative = false;
if (src.charAt(i) == '-') {
negative = true;
i++;
}
while (i < src.length()) {
var c = src.charAt(i);
if (c < '0' || c > '9') break;
parsedAny = true;
whole *= 10;
whole += src.charAt(i++) - '0';
}
if (i < src.length() && src.charAt(i) == '.') {
parsedAny = true;
i++;
while (i < src.length()) {
var c = src.charAt(i);
if (c < '0' || c > '9') break;
parsedAny = true;
fract += src.charAt(i++) - '0';
fract /= 10;
}
}
if (i < src.length() && (src.charAt(i) == 'e' || src.charAt(i) == 'E')) {
i++;
parsedAny = true;
boolean expNegative = false;
boolean parsedE = false;
if (i < src.length()) {
if (src.charAt(i) == '-') {
expNegative = true;
i++;
}
else if (src.charAt(i) == '+') {
i++;
}
}
while (i < src.length()) {
var c = src.charAt(i);
if (c < '0' || c > '9') break;
parsedE = true;
exponent *= 10;
if (expNegative) exponent -= src.charAt(i) - '0';
else exponent += src.charAt(i) - '0';
}
if (!parsedE) return Double.NaN;
}
if (i != src.length()) return Double.NaN;
if (!parsedAny) {
if (negative) return Double.NaN;
return 0.;
}
else if (negative) return -(whole + fract) * power(10, exponent);
else return (whole + fract) * power(10, exponent);
}
}

View File

@ -1,7 +1,5 @@
package me.topchetoeu.j2s.common;
import me.topchetoeu.j2s.common.parsing.Location;
public class SyntaxException extends RuntimeException {
public final Location loc;
public final String msg;

View File

@ -1,3 +0,0 @@
package me.topchetoeu.j2s.common.environment;
public final class Key<T> { }

View File

@ -0,0 +1,3 @@
version: ${version}
name: ${name}
author: TopchetoEU

View File

@ -1,5 +0,0 @@
{
"version": "${version}",
"name": "${name}",
"author": "TopchetoEU"
}

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

@ -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,37 @@
package me.topchetoeu.j2s.common;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestFilename {
@Test public void testShouldParseFilePath() {
var filename = Filename.parse("file://hello.world");
assertEquals("file", filename.protocol);
assertEquals("hello.world", filename.path);
}
@Test public void testShouldParseNoProtocolFilename() {
var filename = Filename.parse("hello.world");
assertEquals("file", filename.protocol);
assertEquals("hello.world", filename.path);
}
@Test public void testShouldParseAdditionalSlashFilename() {
var filename = Filename.parse("test:///hello.world");
assertEquals("test", filename.protocol);
assertEquals("/hello.world", filename.path);
}
@Test public void testShouldParseOneSlashFilename() {
var filename = Filename.parse("test:/hello.world");
assertEquals("file", filename.protocol);
assertEquals("test:/hello.world", filename.path);
}
@Test public void testShouldParseMatroshkaFilename() {
var a = Filename.parse("a://b://hello.world");
assertEquals("a", a.protocol);
assertEquals("b://hello.world", a.path);
var b = Filename.parse(a.path);
assertEquals("b", b.protocol);
assertEquals("hello.world", b.path);
}
}

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

@ -0,0 +1,159 @@
package me.topchetoeu.j2s.common;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestLocation {
@Test public void testShouldCreateLocation() {
var loc = Location.of(new Filename("file", "test.txt"), 10, 5);
assertEquals("test.txt", loc.filename().path);
assertEquals(10, loc.line());
assertEquals(5, loc.start());
}
@Test public void testShouldGetNextLineLocation() {
var loc = Location.of("test.txt:10:5");
var next = loc.nextLine();
assertEquals(new Filename("file", "test.txt"), next.filename());
assertEquals(10, next.line());
assertEquals(0, next.start());
assertEquals(new Filename("file", "test.txt"), loc.filename());
assertEquals(9, loc.line());
assertEquals(4, loc.start());
}
@Test public void testShouldGetNextNthLineLocation() {
var loc = Location.of(new Filename("file", "test.txt"), 10, 5);
var next = loc.nextLine(5);
assertEquals(15, next.line());
assertEquals(0, next.start());
assertEquals(10, loc.line());
assertEquals(5, loc.start());
}
@Test public void testShouldGetNextLocation() {
var loc = Location.of("test:10:5");
var next = loc.add(10);
assertEquals(new Filename("file", "test"), next.filename());
assertEquals(9, next.line());
assertEquals(14, next.start());
assertEquals(new Filename("file", "test"), loc.filename());
assertEquals(9, loc.line());
assertEquals(4, loc.start());
}
@Test public void testShouldParseLocation() {
var loc = Location.of("test.txt:10:5");
assertEquals(new Filename("file", "test.txt"), loc.filename());
assertEquals(9, loc.line());
assertEquals(4, loc.start());
}
@Test public void testShouldParseComplexFilenameLocation() {
var loc = Location.of("testificate://test.txt:10:5");
assertEquals(new Filename("testificate", "test.txt"), loc.filename());
assertEquals(9, loc.line());
assertEquals(4, loc.start());
}
@Test public void testShouldParseNoFilenameLocation() {
var loc = Location.of("10:5");
assertEquals(null, loc.filename());
assertEquals(9, loc.line());
assertEquals(4, loc.start());
}
@Test public void testShouldParseNoStartLocationA() {
var loc = Location.of("file://10:5");
assertEquals(new Filename("file", "10"), loc.filename());
assertEquals(4, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testShouldParseNoStartLocationB() {
var loc = Location.of("file:5");
assertEquals(new Filename("file", "file"), loc.filename());
assertEquals(4, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testShouldParseOnlyFilenameLocationA() {
var loc = Location.of("http://example.org/test.txt");
assertEquals(new Filename("http", "example.org/test.txt"), loc.filename());
assertEquals(-1, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testShouldParseOnlyFilenameLocationB() {
var loc = Location.of("test.txt");
assertEquals(new Filename("file", "test.txt"), loc.filename());
assertEquals(-1, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testShouldParseOnlyFilenameWithColonLocation() {
var loc = Location.of("my-file:bad-file");
assertEquals(new Filename("file", "my-file:bad-file"), loc.filename());
assertEquals(-1, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testShouldParseOnlyFilenameWithTripleColonLocation() {
var loc = Location.of("a:my-file:bad-file");
assertEquals(new Filename("file", "a:my-file:bad-file"), loc.filename());
assertEquals(-1, loc.line());
assertEquals(-1, loc.start());
}
@Test public void testCompareEqualLoc() {
var locA = Location.of("test:10:5");
var locB = Location.of("test:10:5");
assertEquals(0, locA.compareTo(locB));
assertEquals(0, locB.compareTo(locA));
}
@Test public void testCompareNoFileLoc() {
var locA = Location.of("10:5");
var locB = Location.of("11:5");
assertEquals(-1, locA.compareTo(locB));
assertEquals(1, locB.compareTo(locA));
}
@Test public void testCompareOneNoFileLoc() {
var locA = Location.of("10:5");
var locB = Location.of("test:10:5");
assertEquals(-1, locA.compareTo(locB));
assertEquals(1, locB.compareTo(locA));
}
@Test public void testCompareDiffFileLoc() {
var locA = Location.of("a:10:5");
var locB = Location.of("b:10:5");
assertEquals(-1, locA.compareTo(locB));
assertEquals(1, locB.compareTo(locA));
}
@Test public void testCompareDiffLineLoc() {
var locA = Location.of("test:10:5");
var locB = Location.of("test:11:5");
assertEquals(-1, locA.compareTo(locB));
assertEquals(1, locB.compareTo(locA));
}
@Test public void testCompareDiffStartLoc() {
var locA = Location.of("test:10:5");
var locB = Location.of("test:10:10");
assertEquals(-1, locA.compareTo(locB));
assertEquals(1, locB.compareTo(locA));
}
@Test public void testToStringAll() {
var locA = Location.of("test:10:5");
assertEquals("file://test:10:5", locA.toString());
}
@Test public void testToStringNoFilename() {
var locA = Location.of("10:5");
assertEquals("10:5", locA.toString());
}
@Test public void testToStringNoStart() {
var locA = Location.of("file:5");
assertEquals("file://file:5", locA.toString());
}
@Test public void testToStringNoLoc() {
var locA = Location.of("file");
assertEquals("file://file", locA.toString());
}
}

View File

@ -5,14 +5,14 @@ import java.util.Map;
import java.util.Stack;
import java.util.function.Function;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.FunctionBody;
import me.topchetoeu.j2s.common.FunctionMap;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.FunctionMap.FunctionMapBuilder;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.mapping.FunctionMap;
import me.topchetoeu.j2s.common.mapping.FunctionMap.FunctionMapBuilder;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.control.TryNode;
import me.topchetoeu.j2s.compilation.scope.FunctionScope;
import me.topchetoeu.j2s.compilation.scope.Variable;
@ -25,6 +25,7 @@ import java.util.LinkedList;
public final class CompileResult {
public static final Key<Void> DEBUG_LOG = new Key<>();
private FunctionBody body;
public final List<Instruction> instructions;
public final List<CompileResult> children;
public final Map<FunctionNode, CompileResult> childrenMap = new HashMap<>();
@ -71,17 +72,17 @@ public final class CompileResult {
setLocationAndDebug(instructions.size() - 1, loc, type);
}
public Iterable<FunctionBody> bodies() {
var stack = new Stack<FunctionBody>();
stack.push(body());
public Iterable<CompileResult> all() {
var stack = new Stack<CompileResult>();
stack.push(this);
return () -> new Iterator<FunctionBody>() {
@Override public FunctionBody next() {
return () -> new Iterator<CompileResult>() {
@Override public CompileResult next() {
if (stack.empty()) return null;
else {
var res = stack.pop();
for (var el : res.children) {
stack.push(el);
for (var child : res.children) {
stack.push(child);
}
return res;
}
@ -110,6 +111,8 @@ public final class CompileResult {
return map.build(scope.localNames(), scope.capturableNames(), scope.captureNames());
}
public FunctionBody body() {
if (body != null) return body;
var builtChildren = new FunctionBody[children.size()];
for (var i = 0; i < children.size(); i++) builtChildren[i] = children.get(i).body();
@ -124,7 +127,7 @@ public final class CompileResult {
for (var instr : instrRes) System.out.println(instr);
}
return new FunctionBody(
return body = new FunctionBody(
scope.localsCount(), scope.capturablesCount(), scope.capturesCount(),
length, instrRes, builtChildren
);

View File

@ -5,11 +5,11 @@ import java.util.Arrays;
import java.util.List;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class CompoundNode extends Node {

View File

@ -2,13 +2,13 @@ package me.topchetoeu.j2s.compilation;
import java.util.List;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.scope.FunctionScope;
import me.topchetoeu.j2s.compilation.values.VariableNode;

View File

@ -3,8 +3,8 @@ package me.topchetoeu.j2s.compilation;
import java.util.List;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.scope.Variable;
import me.topchetoeu.j2s.compilation.values.VariableNode;

View File

@ -3,8 +3,8 @@ package me.topchetoeu.j2s.compilation;
import java.util.List;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.values.VariableNode;
public class FunctionValueNode extends FunctionNode {

View File

@ -6,13 +6,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.control.BreakNode;
import me.topchetoeu.j2s.compilation.control.ContinueNode;
import me.topchetoeu.j2s.compilation.control.DebugNode;
@ -26,6 +23,9 @@ import me.topchetoeu.j2s.compilation.control.SwitchNode;
import me.topchetoeu.j2s.compilation.control.ThrowNode;
import me.topchetoeu.j2s.compilation.control.TryNode;
import me.topchetoeu.j2s.compilation.control.WhileNode;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.scope.FunctionScope;
import me.topchetoeu.j2s.compilation.values.ArgumentsNode;
import me.topchetoeu.j2s.compilation.values.ArrayNode;

View File

@ -5,11 +5,11 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.function.IntSupplier;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.parsing.Location;
public class LabelContext {
public static final Key<LabelContext> BREAK_CTX = new Key<>();

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
public abstract class Node {
private Location loc;

View File

@ -1,6 +1,6 @@
package me.topchetoeu.j2s.compilation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
public final class Parameter {
public final Location loc;

View File

@ -6,10 +6,10 @@ import java.util.List;
import com.github.bsideup.jabel.Desugar;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.VariableNode;
public class VariableDeclareNode extends Node {

View File

@ -1,15 +1,15 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class BreakNode extends Node {
public final String label;

View File

@ -1,15 +1,15 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class ContinueNode extends Node {
public final String label;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class DebugNode extends Node {
@Override public void compileFunctions(CompileResult target) {

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.VariableNode;
import me.topchetoeu.j2s.compilation.values.constants.BoolNode;
import me.topchetoeu.j2s.compilation.values.operations.IndexNode;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class DoWhileNode extends Node {
public final Node condition, body;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.VariableNode;
public class ForInNode extends Node {

View File

@ -1,17 +1,17 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.VariableDeclareNode;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class ForNode extends Node {
public final Node declaration, assignment, condition, body;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class IfNode extends Node {
public final Node condition, body, elseBody;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class ReturnNode extends Node {
public final Node value;

View File

@ -4,17 +4,17 @@ import java.util.ArrayList;
import java.util.HashMap;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class SwitchNode extends Node {
public static class SwitchCase {

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class ThrowNode extends Node {
public final Node value;

View File

@ -1,17 +1,17 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.CompoundNode;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class TryNode extends Node {
public final CompoundNode tryBody;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class WhileNode extends Node {
public final Node condition, body;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.j2s.common.json;
package me.topchetoeu.j2s.compilation.json;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Metadata;
import me.topchetoeu.j2s.common.StringifyUtils;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class JSON {
public static ParseRes<JSONElement> parseString(Source src, int i) {
@ -110,37 +110,10 @@ public class JSON {
}
public static String stringify(JSONElement el) {
if (el.isNumber()) {
var d = el.number();
if (d == Double.NEGATIVE_INFINITY) return "-Infinity";
if (d == Double.POSITIVE_INFINITY) return "Infinity";
if (Double.isNaN(d)) return "NaN";
return BigDecimal.valueOf(d).stripTrailingZeros().toPlainString();
}
if (el.isNumber()) return StringifyUtils.quoteNumber(el.number());
if (el.isString()) return StringifyUtils.quoteString(el.string());
if (el.isBoolean()) return el.bool() ? "true" : "false";
if (el.isNull()) return "null";
if (el.isString()) {
var res = new StringBuilder("\"");
var alphabet = "0123456789ABCDEF".toCharArray();
for (var c : el.string().toCharArray()) {
if (c < 32 || c >= 127) {
res
.append("\\u")
.append(alphabet[(c >> 12) & 0xF])
.append(alphabet[(c >> 8) & 0xF])
.append(alphabet[(c >> 4) & 0xF])
.append(alphabet[(c >> 0) & 0xF]);
}
else if (c == '\\')
res.append("\\\\");
else if (c == '"')
res.append("\\\"");
else res.append(c);
}
return res.append('"').toString();
}
if (el.isList()) {
var res = new StringBuilder().append("[");
for (int i = 0; i < el.list().size(); i++) {
@ -156,7 +129,7 @@ public class JSON {
for (int i = 0; i < entries.size(); i++) {
if (i != 0) res.append(",");
res.append(stringify(JSONElement.string(entries.get(i).getKey())));
res.append(StringifyUtils.quoteString(entries.get(i).getKey()));
res.append(":");
res.append(stringify(entries.get(i).getValue()));
}

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.json;
package me.topchetoeu.j2s.compilation.json;
public class JSONElement {
public static enum Type {

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.json;
package me.topchetoeu.j2s.compilation.json;
import java.util.ArrayList;
import java.util.Arrays;

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.json;
package me.topchetoeu.j2s.compilation.json;
import java.util.Collection;
import java.util.HashMap;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.members;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.ObjectNode;
public class FieldMemberNode implements Member {

View File

@ -1,6 +1,6 @@
package me.topchetoeu.j2s.compilation.members;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
public interface Member {

View File

@ -3,16 +3,16 @@ package me.topchetoeu.j2s.compilation.members;
import java.util.Arrays;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.CompoundNode;
import me.topchetoeu.j2s.compilation.FunctionNode;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.ObjectNode;
import me.topchetoeu.j2s.compilation.values.VariableNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode;

View File

@ -1,4 +1,6 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.compilation.parsing;
import me.topchetoeu.j2s.common.Location;
public class ParseRes<T> {
public static enum State {
@ -33,19 +35,20 @@ public class ParseRes<T> {
if (!state.isSuccess()) return this;
return new ParseRes<>(state, null, null, result, this.n + n);
}
@SuppressWarnings("unchecked")
public <T2> ParseRes<T2> chainError() {
if (isSuccess()) throw new RuntimeException("Can't transform a ParseRes that hasn't failed");
return new ParseRes<>(state, errorLocation, error, null, 0);
return (ParseRes<T2>)this;
}
@SuppressWarnings("unchecked")
public <T2> ParseRes<T2> chainError(ParseRes<?> other) {
if (!this.isError()) return other.chainError();
return (ParseRes<T2>) this;
if (this.isError()) return other.chainError();
return (ParseRes<T2>)this;
}
@SuppressWarnings("unchecked")
public <T2> ParseRes<T2> chainError(Location loc, String error) {
if (!this.isError()) return new ParseRes<>(State.ERROR, loc, error, null, 0);
return (ParseRes<T2>) this;
return (ParseRes<T2>)this;
}
public boolean isSuccess() { return state.isSuccess(); }
@ -63,7 +66,6 @@ public class ParseRes<T> {
return new ParseRes<>(State.SUCCESS, null, null, val, i);
}
@SafeVarargs
@SuppressWarnings("all")
public static <T> ParseRes<T> first(Source src, int i, Parser ...parsers) {
int n = Parsing.skipEmpty(src, i);

View File

@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.compilation.parsing;
public interface Parser<T> {
public ParseRes<T> parse(Source src, int i);

View File

@ -1,6 +1,4 @@
package me.topchetoeu.j2s.common.parsing;
import me.topchetoeu.j2s.common.SyntaxException;
package me.topchetoeu.j2s.compilation.parsing;
public class Parsing {
public static boolean isDigit(Character c) {
@ -18,14 +16,13 @@ public class Parsing {
}
public static int skipEmpty(Source src, int i) {
return skipEmpty(src, i, true);
}
public static int skipEmpty(Source src, int i, boolean noComments) {
int n = 0;
if (i == 0 && src.is(0, "#!")) {
while (!src.is(n, '\n')) n++;
while (!src.is(n, '\n')) {
if (n >= src.size()) return src.size();
n++;
}
n++;
}
@ -88,7 +85,7 @@ public class Parsing {
if (i + n >= src.size()) return ParseRes.error(src.loc(i), "Invalid hexadecimal escape sequence");
int val = fromHex(src.at(i + n));
if (val == -1) throw new SyntaxException(src.loc(i + n), "Invalid hexadecimal escape sequence");
if (val == -1) return ParseRes.error(src.loc(i + n), "Invalid hexadecimal escape sequence");
n++;
newC = (newC << 4) | val;
@ -103,7 +100,7 @@ public class Parsing {
if (i + n >= src.size()) return ParseRes.error(src.loc(i), "Invalid Unicode escape sequence");
int val = fromHex(src.at(i + n));
if (val == -1) throw new SyntaxException(src.loc(i + n), "Invalid Unicode escape sequence");
if (val == -1) return ParseRes.error(src.loc(i + n), "Invalid Unicode escape sequence");
n++;
newC = (newC << 4) | val;

View File

@ -1,8 +1,10 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.compilation.parsing;
import java.util.function.Predicate;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
public class Source {
public final Environment env;
@ -12,6 +14,8 @@ public class Source {
private int[] lineStarts;
public Location loc(int offset) {
if (offset < 0) offset = 0;
if (offset > src.length()) offset = src.length();
return new SourceLocation(filename, lineStarts, offset);
}
public boolean is(int i, char c) {

View File

@ -1,7 +1,10 @@
package me.topchetoeu.j2s.common.parsing;
package me.topchetoeu.j2s.compilation.parsing;
import java.util.Objects;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
public class SourceLocation extends Location {
private int[] lineStarts;
private int line;

View File

@ -1,6 +1,6 @@
package me.topchetoeu.j2s.compilation.patterns;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
/**

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;

View File

@ -3,13 +3,13 @@ package me.topchetoeu.j2s.compilation.values;
import java.util.ArrayList;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class ArrayNode extends Node {

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;

View File

@ -4,16 +4,16 @@ import java.util.LinkedList;
import java.util.List;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.members.FieldMemberNode;
import me.topchetoeu.j2s.compilation.members.Member;
import me.topchetoeu.j2s.compilation.members.PropertyMemberNode;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode;

View File

@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class RegexNode extends Node {
public final String pattern, flags;

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
public class VariableNode extends Node implements ChangeTarget {

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;

View File

@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class NumberNode extends Node {
public final double value;

View File

@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class StringNode extends Node {
public final String value;

View File

@ -1,9 +1,9 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.patterns.AssignTarget;

View File

@ -3,14 +3,14 @@ package me.topchetoeu.j2s.compilation.values.operations;
import java.util.ArrayList;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class CallNode extends Node {
public final Node func;

View File

@ -1,14 +1,14 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class DiscardNode extends Node {

View File

@ -1,14 +1,14 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class LazyAndNode extends Node {
public final Node first, second;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class LazyOrNode extends Node {

View File

@ -6,14 +6,14 @@ import java.util.Map;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.patterns.AssignTargetLike;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode;

View File

@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.compilation.values.VariableNode;
public class TypeofNode extends Node {

View File

@ -1,8 +1,8 @@
package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.FunctionNode;
import me.topchetoeu.j2s.compilation.Node;

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

@ -0,0 +1,98 @@
package me.topchetoeu.j2s.compilation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.parsing.ParseRes;
public class TestParseRes {
@Test public void testCreateFailed() {
var res = ParseRes.failed();
assertEquals(false, res.isSuccess());
assertEquals(true, res.isFailed());
assertEquals(false, res.isError());
assertEquals(0, res.n);
assertEquals(null, res.result);
assertEquals(null, res.errorLocation);
assertEquals(null, res.error);
}
@Test public void testCreateError() {
var res = ParseRes.error(Location.of("test:10:5"), "test");
assertEquals(false, res.isSuccess());
assertEquals(false, res.isFailed());
assertEquals(true, res.isError());
assertEquals(0, res.n);
assertEquals(null, res.result);
assertEquals(Location.of("test:10:5"), res.errorLocation);
assertEquals("test", res.error);
}
@Test public void testCreateResult() {
var res = ParseRes.res("test", 10);
assertEquals(true, res.isSuccess());
assertEquals(false, res.isFailed());
assertEquals(false, res.isError());
assertEquals(10, res.n);
assertEquals("test", res.result);
assertEquals(null, res.errorLocation);
assertEquals(null, res.error);
}
@Test public void testChainFailed() {
var a = ParseRes.<Integer>failed();
var b1 = a.<String>chainError();
assertEquals(a, b1);
var b2 = a.<String>chainError(Location.of("test:1:2"), "test");
assertEquals(true, b2.isError());
assertEquals("test", b2.error);
}
@Test public void testChainError() {
var a = ParseRes.<Integer>error(Location.of("test:1:2"), "test");
var b1 = a.<String>chainError();
assertEquals(a, b1);
var b2 = a.<String>chainError(Location.of("test:1:2"), "test");
assertEquals(a, b2);
}
@Test public void testChainResult() {
var a = ParseRes.<Integer>res(10, 6);
assertThrows(RuntimeException.class, () -> a.<String>chainError());
var b1 = a.<String>chainError(Location.of("test:1:2"), "test");
assertEquals(true, b1.isError());
assertEquals("test", b1.error);
}
@Test public void testShouldAdd5() {
var a = ParseRes.res("test", 6);
var b = a.addN(5);
assertEquals(11, b.n);
}
@Test public void testShouldSet5() {
var a = ParseRes.res("test", 6);
var b = a.setN(5);
assertEquals(5, b.n);
}
@Test public void testShouldNotAdd() {
var a = ParseRes.failed();
var b = a.addN(5);
assertEquals(0, b.n);
}
@Test public void testShouldNotSet() {
var a = ParseRes.failed();
var b = a.setN(5);
assertEquals(0, b.n);
}
}

View File

@ -0,0 +1,65 @@
package me.topchetoeu.j2s.compilation;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class TestSource {
private Source mkSource(String src) {
return new Source(new Environment(), Filename.parse("test"), src);
}
@Test public void testShouldCreate() {
new Source(new Environment(), Filename.parse("test"), "my little source :)");
new Source(null, Filename.parse("test"), "my little source :)");
new Source("my little source :)");
}
@Test public void testShouldGet() {
var src = mkSource("1234567890");
assertEquals('1', src.at(0));
assertEquals('6', src.at(5));
}
@Test public void testShouldThrowOutOfRange() {
var src = mkSource("1234567890");
assertThrows(IndexOutOfBoundsException.class, () -> src.at(-1));
assertThrows(IndexOutOfBoundsException.class, () -> src.at(10));
}
@Test public void testImmutableSrcLoc() {
var src = mkSource("1234567890");
var loc = src.loc(5);
// kinda stupid
for (var i = 0; i < 1000; i++) {
assertEquals(5, loc.start());
assertEquals(0, loc.line());
assertEquals(Filename.parse("test"), loc.filename());
}
}
@Test public void testSingleLineSourceLocation() {
var src = mkSource("1234567890");
assertEquals(Location.of("test:1:1"), src.loc(-5));
assertEquals(Location.of("test:1:1"), src.loc(0));
assertEquals(Location.of("test:1:10"), src.loc(9));
assertEquals(Location.of("test:1:11"), src.loc(14));
}
@Test public void testMultilineSourceLocation() {
var src = mkSource("123\n456\n\n789\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
assertEquals(Location.of("test:1:1"), src.loc(-5));
assertEquals(Location.of("test:1:1"), src.loc(0));
assertEquals(Location.of("test:1:4"), src.loc(3));
assertEquals(Location.of("test:2:1"), src.loc(4));
assertEquals(Location.of("test:2:4"), src.loc(7));
assertEquals(Location.of("test:3:1"), src.loc(8));
assertEquals(Location.of("test:4:1"), src.loc(9));
assertEquals(Location.of("test:4:2"), src.loc(10));
assertEquals(Location.of("test:4:4"), src.loc(12));
assertEquals(Location.of("test:5:1"), src.loc(13));
assertEquals(Location.of("test:19:1"), src.loc(50));
}
}

View File

@ -0,0 +1,68 @@
package me.topchetoeu.j2s.compilation.parsing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class TestParseString {
@Test public void notAString() {
var res = Parsing.parseString(new Source("var a = 10"), 0);
assertEquals(true, res.isFailed());
}
@Test public void simple() {
var src = new Source("\"this is a test\"");
var res = Parsing.parseString(src, 0);
assertEquals(true, res.isSuccess());
assertEquals("this is a test", res.result);
assertEquals(16, res.n);
}
@Test public void simpleEscaped() {
var src = new Source("\'this\\\\ is \\n some \\'\\\"\\\n escapes for you :\\)\'");
var res = Parsing.parseString(src, 0);
assertEquals(true, res.isSuccess());
assertEquals("this\\ is \n some '\" escapes for you :)", res.result);
assertEquals(46, res.n);
}
@Test public void allEscaped() {
var src = new Source("'\\b\\t\\n\\f\\r\\0\\'\\x01\\u0123'");
var res = Parsing.parseString(src, 0);
assertEquals(true, res.isSuccess());
assertEquals("\b\t\n\f\r\0'\u0001\u0123", res.result);
assertEquals(26, res.n);
}
@Test public void shouldFailOctal() {
var res1 = Parsing.parseString(new Source("'\\012'"), 0);
assertEquals(true, res1.isError());
var res2 = Parsing.parseString(new Source("'\\123'"), 0);
assertEquals(true, res2.isError());
}
@Test public void shouldFailIncompleteHex() {
var res1 = Parsing.parseString(new Source("'\\x"), 0);
assertEquals(true, res1.isError());
var res2 = Parsing.parseString(new Source("'\\x1turd"), 0);
assertEquals(true, res2.isError());
var res3 = Parsing.parseString(new Source("'\\xturd"), 0);
assertEquals(true, res3.isError());
}
@Test public void shouldFailIncompleteUnicode() {
var res1 = Parsing.parseString(new Source("'\\u"), 0);
assertEquals(true, res1.isError());
var res2 = Parsing.parseString(new Source("'\\u123turd"), 0);
assertEquals(true, res2.isError());
var res3 = Parsing.parseString(new Source("'\\uturd"), 0);
assertEquals(true, res3.isError());
}
@Test public void unterminated() {
var src = new Source("\"this is a test");
var res = Parsing.parseString(src, 0);
assertEquals(true, res.isError());
}
}

View File

@ -0,0 +1,51 @@
package me.topchetoeu.j2s.compilation.parsing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class TestSkipWhite {
@Test public void shBang() {
var res1 = Parsing.skipEmpty(new Source("#!my-shbang\n10"), 0);
assertEquals(12, res1);
var res2 = Parsing.skipEmpty(new Source("#!fin"), 0);
assertEquals(5, res2);
}
@Test public void simple() {
var res1 = Parsing.skipEmpty(new Source("2134 45324"), 4);
assertEquals(3, res1);
var res2 = Parsing.skipEmpty(new Source("2134 "), 4);
assertEquals(3, res2);
}
@Test public void nothing() {
var res1 = Parsing.skipEmpty(new Source("12345678"), 4);
assertEquals(0, res1);
var res2 = Parsing.skipEmpty(new Source("1234"), 4);
assertEquals(0, res2);
}
@Test public void singleLineComment() {
var res1 = Parsing.skipEmpty(new Source("123// test\n54314214"), 3);
assertEquals(8, res1);
var res2 = Parsing.skipEmpty(new Source("123// test"), 3);
assertEquals(7, res2);
}
@Test public void multilineComment() {
var res1 = Parsing.skipEmpty(new Source("123/*test*/54314214"), 3);
assertEquals(8, res1);
var res2 = Parsing.skipEmpty(new Source("123/*test*/"), 3);
assertEquals(8, res2);
var res3 = Parsing.skipEmpty(new Source("123/*test"), 3);
assertEquals(6, res3);
}
}

View File

@ -1,12 +1,12 @@
package me.topchetoeu.j2s.runtime;
package me.topchetoeu.j2s.repl;
import java.util.HashSet;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.json.JSONList;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.compilation.json.JSONElement;
import me.topchetoeu.j2s.compilation.json.JSONList;
import me.topchetoeu.j2s.compilation.json.JSONMap;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ArrayValue;

View File

@ -16,14 +16,20 @@ import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.j2s.common.Metadata;
import me.topchetoeu.j2s.common.Reading;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
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.Debugger;
import me.topchetoeu.j2s.repl.debug.SimpleDebugger;
@ -33,7 +39,6 @@ import me.topchetoeu.j2s.runtime.Compiler;
import me.topchetoeu.j2s.runtime.Engine;
import me.topchetoeu.j2s.runtime.EventLoop;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.JSONConverter;
import me.topchetoeu.j2s.runtime.debug.DebugContext;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;
@ -43,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.ArrayValue;
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.StringValue;
import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue;
@ -61,8 +62,8 @@ public class SimpleRepl {
var body = res.body();
DebugContext.get(env).onSource(filename, raw);
for (var el : res.bodies()) {
DebugContext.get(env).onFunctionLoad(el, res.map(mapper));
for (var el : res.all()) {
DebugContext.get(env).onFunctionLoad(el.body(), el.map(mapper));
}
return new CodeFunction(env, filename.toString(), body, new Value[0][]);
@ -385,13 +386,29 @@ public class SimpleRepl {
if (num.isInt()) return num;
else return NumberValue.of(num.getDouble() - num.getDouble() % 1);
}
else return NumberValue.parseInt(args.get(0).toString(), radix, false);
else {
if (radix < 2 || radix > 36) return NumberValue.NAN;
var str = args.get(0).toString().trim();
var numRes = Parsing.parseInt(new Source(str), 0, "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, radix), true);
if (numRes.isSuccess()) {
if (numRes.n == str.length()) return NumberValue.of(numRes.result);
}
return NumberValue.NAN;
}
}));
res.defineOwnField(env, "parseFloat", new NativeFunction(args -> {
if (args.get(0) instanceof NumberValue) {
return args.get(0);
}
else return NumberValue.parseFloat(args.get(0).toString(), false);
else {
var str = args.get(0).toString().trim();
var numRes = Parsing.parseFloat(new Source(str), 0, true);
if (numRes.isSuccess()) {
if (numRes.n == str.length()) return NumberValue.of(numRes.result);
}
return NumberValue.NAN;
}
}));
res.defineOwnField(env, "isNaN", new NativeFunction(args -> BoolValue.of(args.get(0).isNaN())));
@ -684,14 +701,14 @@ public class SimpleRepl {
res.defineOwnField(env, "invoke", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0);
var self = args.get(1);
var funcArgs = (ArrayValue)args.get(2);
var funcArgs = (ArrayLikeValue)args.get(2);
return func.apply(env, self, funcArgs.toArray());
}));
res.defineOwnField(env, "construct", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0);
var target = args.get(1);
var funcArgs = (ArrayValue)args.get(2);
var funcArgs = (ArrayLikeValue)args.get(2);
if (target == Value.UNDEFINED) return func.constructNoSelf(env, funcArgs.toArray());
else return func.construct(env, target, funcArgs.toArray());

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.repl;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONMap;
public class V8Error {
public final String message;

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 {
@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 {
@Override protected int onGet(int i) {

View File

@ -1,8 +1,8 @@
package me.topchetoeu.j2s.runtime.values.objects.buffers;
package me.topchetoeu.j2s.repl.buffers;
import java.util.WeakHashMap;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;

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 {
@Override protected int onGet(int i) {

View File

@ -12,9 +12,9 @@ import java.util.HashMap;
import me.topchetoeu.j2s.common.Metadata;
import me.topchetoeu.j2s.common.Reading;
import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONList;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONList;
import me.topchetoeu.j2s.compilation.json.JSONMap;
import me.topchetoeu.j2s.repl.debug.WebSocketMessage.Type;
public class DebugServer {

View File

@ -7,7 +7,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.IntUnaryOperator;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.KeyCache;

View File

@ -11,25 +11,25 @@ import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.FunctionBody;
import me.topchetoeu.j2s.common.FunctionMap;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Metadata;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.common.Instruction.Type;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.json.JSONList;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.common.mapping.FunctionMap;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONElement;
import me.topchetoeu.j2s.compilation.json.JSONList;
import me.topchetoeu.j2s.compilation.json.JSONMap;
import me.topchetoeu.j2s.repl.JSONConverter;
import me.topchetoeu.j2s.repl.SimpleRepl;
import me.topchetoeu.j2s.runtime.Compiler;
import me.topchetoeu.j2s.runtime.Engine;
import me.topchetoeu.j2s.runtime.EventLoop;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.JSONConverter;
import me.topchetoeu.j2s.runtime.debug.DebugContext;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;

View File

@ -1,6 +1,6 @@
package me.topchetoeu.j2s.repl.debug;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue;

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.repl.debug;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONMap;
public class V8Error {
public final String message;

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.repl.debug;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONMap;
public class V8Event {
public final String name;

View File

@ -2,9 +2,9 @@ package me.topchetoeu.j2s.repl.debug;
import java.util.Map;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONElement;
import me.topchetoeu.j2s.compilation.json.JSONMap;
public class V8Message {
public final String name;

View File

@ -1,7 +1,7 @@
package me.topchetoeu.j2s.repl.debug;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.compilation.json.JSON;
import me.topchetoeu.j2s.compilation.json.JSONMap;
public class V8Result {
public final int id;

View File

@ -2,9 +2,9 @@ package me.topchetoeu.j2s.repl.mapping;
import java.util.function.Function;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.functions.FunctionValue;

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;
import me.topchetoeu.j2s.common.Environment;
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;
private Value[] args;
private boolean shadowed;
public ArgumentsValue(Frame frame, Value... args) {
super(args);
private void shadow() {
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.args = frame.args;
this.shadowed = false;
setPrototype(e -> null);
}
}

Some files were not shown because too many files have changed in this diff Show More