Compare commits

...

23 Commits

Author SHA1 Message Date
fffeac9bac fix: name was always 'name'
All checks were successful
tagged-release / Tagged Release (push) Successful in 4m14s
2025-01-24 04:18:35 +02:00
166e9c0470 bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 3m56s
2025-01-24 03:26:14 +02:00
6125772038 add package uploading 2025-01-24 02:45:26 +02:00
1e982cd2ef some minor restructuring 2025-01-24 00:22:15 +02:00
4389d115b6 use only babel 2025-01-24 00:22:03 +02:00
208444381e move FunctionMap logic away from core 2025-01-24 00:21:51 +02:00
eff076f6fe bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 3m56s
2025-01-22 20:34:46 +02:00
24a4a01d8e fix warnings 2025-01-22 20:34:36 +02:00
b9a397a7b9 specify babel plugins separately 2025-01-22 20:34:31 +02:00
40f6cfe616 fix: make Function.compile do less stuff 2025-01-22 20:34:00 +02:00
f712fb09ae refactor: merge TYPEOF instruction into OPERATION 2025-01-22 20:32:55 +02:00
6355a48c6b fix: forEach is cringe 2025-01-22 20:21:32 +02:00
343684f9ce move more instructions as intrinsics 2025-01-22 03:57:32 +02:00
582753440b fix: remove unneeded LOAD_REGEX instruction 2025-01-22 01:54:29 +02:00
01e86b5e70 Merge pull request 'Write some tests' (#33) from topchetoeu/tests into master
Reviewed-on: #33
2025-01-15 18:23:24 +00:00
29b0c91c5d fix: function mappings were registered incorrectly 2025-01-15 20:12:52 +02:00
961c8cefcc make arguments null prototype, to follow spec closer 2025-01-15 19:54:12 +02:00
3b512b64eb move buffers out of runtime 2025-01-15 19:52:53 +02:00
0118379d4e simple func map tests 2025-01-15 19:51:35 +02:00
1be1cded9f delete placeholder tests 2025-01-15 19:51:09 +02:00
c0b23d50e5 make common project classes hierarchy flat 2025-01-12 04:31:32 +02:00
cacffd01e8 move JSON and parsing logic to compiler project, decouple JSON and parser from engine logic 2025-01-12 04:27:43 +02:00
a115843351 parseRes tests 2025-01-12 03:23:35 +02:00
145 changed files with 1403 additions and 935 deletions

View File

@@ -25,10 +25,14 @@ jobs:
gradle-version: "8.10" gradle-version: "8.10"
- name: Build - name: Build
run: gradle build run: gradle build
- name: Publish
run: gradle publish
env:
ACCESS_TOKEN: "${{secrets.PACKAGE_TOKEN}}"
REPO_URL: "${{github.server_url}}/api/packages/${{github.repository_owner}}/maven"
- name: Create release - name: Create release
uses: "https://gitea.com/actions/gitea-release-action@main" uses: "https://gitea.com/actions/gitea-release-action@main"
with: with:
# api_key: "${{secrets.TOKEN}}"
files: | files: |
LICENSE LICENSE
build/libs/*.jar build/libs/*.jar

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 // We'll register the source and function source mappings for debugging
DebugContext.get(env).onSource(filename, raw); DebugContext.get(env).onSource(filename, raw);
for (var el : res.bodies()) { for (var el : res.all()) {
DebugContext.get(env).onFunctionLoad(el, res.map(mapper)); DebugContext.get(env).onFunctionLoad(el.body(), el.map(mapper));
} }
// Finally, we will construct the function // Finally, we will construct the function

View File

@@ -11,7 +11,7 @@ tasks.wrapper {
} }
tasks.build { tasks.build {
subprojects.forEach { proj -> for (proj in subprojects) {
dependsOn(proj.tasks.named("build")); dependsOn(proj.tasks.named("build"));
doLast { doLast {
copy { copy {

View File

@@ -9,4 +9,7 @@ java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(17); languageVersion = JavaLanguageVersion.of(17);
} }
withJavadocJar();
withSourcesJar();
} }

View File

@@ -1,5 +1,6 @@
plugins { plugins {
id("java"); id("java");
id("maven-publish");
} }
version = rootProject.version; version = rootProject.version;
@@ -20,3 +21,27 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2"); testImplementation("org.junit.jupiter:junit-jupiter:5.9.2");
testRuntimeOnly("org.junit.platform:junit-platform-launcher"); testRuntimeOnly("org.junit.platform:junit-platform-launcher");
} }
publishing {
repositories {
maven {
name = "Gitea";
url = uri(System.getenv("REPO_URL") ?: "");
credentials(HttpHeaderCredentials::class) {
name = "Authorization";
value = "token ${System.getenv("ACCESS_TOKEN")}";
}
authentication {
create<HttpHeaderAuthentication>("header");
}
}
}
publications {
create<MavenPublication>("maven") {
from(components["java"]);
}
}
}

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.environment; package me.topchetoeu.j2s.common;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;

View File

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

View File

@@ -0,0 +1,62 @@
package me.topchetoeu.j2s.common;
import java.util.Arrays;
import java.util.regex.Pattern;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
public interface FunctionMap {
public static final FunctionMap EMPTY = new FunctionMap() {
@Override public Location first() {
return null;
}
@Override public Location last() {
return null;
}
@Override public Location toLocation(int i, boolean approximate) {
return null;
}
@Override public BreakpointType getBreakpoint(int i) {
return BreakpointType.NONE;
}
@Override public Iterable<Location> breakpoints(Location start, Location end) {
return Arrays.asList();
}
@Override public Location correctBreakpoint(Location i) {
return null;
}
@Override public Iterable<Location> correctBreakpoint(Pattern filename, int line, int column) {
return Arrays.asList();
}
@Override public String[] localNames() {
return null;
}
@Override public String[] capturableNames() {
return null;
}
@Override public String[] captureNames() {
return null;
}
};
Location first();
Location last();
Location toLocation(int i, boolean approximate);
default Location toLocation(int i) {
return toLocation(i, false);
}
BreakpointType getBreakpoint(int i);
Location correctBreakpoint(Location i);
Iterable<Location> correctBreakpoint(Pattern filename, int line, int column);
Iterable<Location> breakpoints(Location start, Location end);
String[] localNames();
String[] capturableNames();
String[] captureNames();
}

View File

@@ -4,8 +4,6 @@ import java.util.HashMap;
import java.util.function.IntFunction; import java.util.function.IntFunction;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import me.topchetoeu.j2s.common.parsing.Location;
public class Instruction { public class Instruction {
public static enum Type { public static enum Type {
RETURN(0x00), RETURN(0x00),
@@ -33,7 +31,6 @@ public class Instruction {
LOAD_FUNC(0x30), LOAD_FUNC(0x30),
LOAD_ARR(0x31), LOAD_ARR(0x31),
LOAD_OBJ(0x32), LOAD_OBJ(0x32),
LOAD_REGEX(0x33),
LOAD_GLOB(0x38), LOAD_GLOB(0x38),
LOAD_INTRINSICS(0x39), LOAD_INTRINSICS(0x39),
@@ -54,15 +51,11 @@ public class Instruction {
STORE_MEMBER_INT(0x4A), STORE_MEMBER_INT(0x4A),
STORE_MEMBER_STR(0x4B), STORE_MEMBER_STR(0x4B),
DEF_PROP(0x50), GLOB_GET(0x50),
DEF_FIELD(0x51), GLOB_SET(0x51),
KEYS(0x52), GLOB_DEF(0x52),
TYPEOF(0x53),
OPERATION(0x54),
GLOB_GET(0x60), OPERATION(0x56);
GLOB_SET(0x61),
GLOB_DEF(0x62);
private static final HashMap<Integer, Type> types = new HashMap<>(); private static final HashMap<Integer, Type> types = new HashMap<>();
public final int numeric; public final int numeric;
@@ -289,9 +282,6 @@ public class Instruction {
return new Instruction(Type.LOAD_MEMBER_STR, member); return new Instruction(Type.LOAD_MEMBER_STR, member);
} }
public static Instruction loadRegex(String pattern, String flags) {
return new Instruction(Type.LOAD_REGEX, pattern, flags);
}
// TODO: make this capturing a concern of the compiler // TODO: make this capturing a concern of the compiler
public static Instruction loadFunc(int id, String name, int[] captures) { public static Instruction loadFunc(int id, String name, int[] captures) {
var args = new Object[2 + captures.length]; var args = new Object[2 + captures.length];
@@ -313,8 +303,8 @@ public class Instruction {
return new Instruction(Type.DUP, count, offset); return new Instruction(Type.DUP, count, offset);
} }
public static Instruction storeVar(int i, boolean keep, boolean initialize) { public static Instruction storeVar(int i, boolean keep) {
return new Instruction(Type.STORE_VAR, i, keep, initialize); return new Instruction(Type.STORE_VAR, i, keep);
} }
public static Instruction storeMember() { public static Instruction storeMember() {
@@ -342,24 +332,6 @@ public class Instruction {
return new Instruction(Type.DISCARD); return new Instruction(Type.DISCARD);
} }
public static Instruction typeof() {
return new Instruction(Type.TYPEOF);
}
public static Instruction typeof(String varName) {
return new Instruction(Type.TYPEOF, varName);
}
public static Instruction keys(boolean own, boolean onlyEnumerable) {
return new Instruction(Type.KEYS, own, onlyEnumerable);
}
public static Instruction defProp(boolean setter) {
return new Instruction(Type.DEF_PROP, setter);
}
public static Instruction defField() {
return new Instruction(Type.DEF_FIELD);
}
public static Instruction operation(Operation op) { public static Instruction operation(Operation op) {
return new Instruction(Type.OPERATION, op); return new Instruction(Type.OPERATION, op);
} }

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.ArrayList;
import java.util.Objects; import java.util.Objects;
import me.topchetoeu.j2s.common.Metadata;
public abstract class Location implements Comparable<Location> { public abstract class Location implements Comparable<Location> {
public static final Location INTERNAL = Location.of(new Filename(Metadata.name(), "native"), -1, -1); public static final Location INTERNAL = Location.of(new Filename(Metadata.name(), "native"), -1, -1);

View File

@@ -31,7 +31,7 @@ public class Metadata {
AUTHOR = value; AUTHOR = value;
break; break;
case "name": case "name":
NAME = name; NAME = value;
break; break;
default: default:
throw new RuntimeException(String.format("%s:%s: Unexpected metadata key '%s'", file, line, name)); throw new RuntimeException(String.format("%s:%s: Unexpected metadata key '%s'", file, line, name));
@@ -44,15 +44,15 @@ public class Metadata {
} }
public static String version() { public static String version() {
if (VERSION.equals("$" + "{VERSION}")) return "1337-devel"; if (VERSION.equals("${VERSION}")) return "1337-devel";
else return VERSION; else return VERSION;
} }
public static String author() { public static String author() {
if (AUTHOR.equals("$" + "{AUTHOR}")) return "anonymous"; if (AUTHOR.equals("${AUTHOR}")) return "anonymous";
else return AUTHOR; else return AUTHOR;
} }
public static String name() { public static String name() {
if (NAME.equals("$" + "{NAME}")) return "some-product"; if (NAME.equals("${NAME}")) return "some-product";
else return NAME; else return NAME;
} }
} }

View File

@@ -3,36 +3,37 @@ package me.topchetoeu.j2s.common;
import java.util.HashMap; import java.util.HashMap;
public enum Operation { public enum Operation {
INSTANCEOF(1, 2), TYPEOF(0x10, 1),
IN(2, 2), INSTANCEOF(0x11, 2),
IN(0x12, 2),
MULTIPLY(3, 2), MULTIPLY(0x20, 2),
DIVIDE(4, 2), DIVIDE(0x21, 2),
MODULO(5, 2), MODULO(0x22, 2),
ADD(6, 2), ADD(0x23, 2),
SUBTRACT(7, 2), SUBTRACT(0x24, 2),
USHIFT_RIGHT(8, 2), USHIFT_RIGHT(0x30, 2),
SHIFT_RIGHT(9, 2), SHIFT_RIGHT(0x31, 2),
SHIFT_LEFT(10, 2), SHIFT_LEFT(0x32, 2),
GREATER(11, 2), GREATER(0x40, 2),
LESS(12, 2), LESS(0x41, 2),
GREATER_EQUALS(13, 2), GREATER_EQUALS(0x42, 2),
LESS_EQUALS(14, 2), LESS_EQUALS(0x43, 2),
LOOSE_EQUALS(15, 2), LOOSE_EQUALS(0x44, 2),
LOOSE_NOT_EQUALS(16, 2), LOOSE_NOT_EQUALS(0x45, 2),
EQUALS(17, 2), EQUALS(0x46, 2),
NOT_EQUALS(18, 2), NOT_EQUALS(0x47, 2),
AND(19, 2), AND(0x50, 2),
OR(20, 2), OR(0x51, 2),
XOR(21, 2), XOR(0x52, 2),
NEG(23, 1), NEG(0x60, 1),
POS(24, 1), POS(0x61, 1),
NOT(25, 1), NOT(0x62, 1),
INVERSE(26, 1); INVERSE(0x63, 1);
private static final HashMap<Integer, Operation> operations = new HashMap<>(); private static final HashMap<Integer, Operation> operations = new HashMap<>();

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; package me.topchetoeu.j2s.common;
import me.topchetoeu.j2s.common.parsing.Location;
public class SyntaxException extends RuntimeException { public class SyntaxException extends RuntimeException {
public final Location loc; public final Location loc;
public final String msg; public final String msg;

View File

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

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,10 @@
package me.topchetoeu.j2s.common; package me.topchetoeu.j2s.common;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
public class TestEnvironment { public class TestEnvironment {
private final Key<String> FOO = new Key<>(); private final Key<String> FOO = new Key<>();
private final Key<Void> MARKER = new Key<>(); private final Key<Void> MARKER = new Key<>();
@@ -18,55 +15,55 @@ public class TestEnvironment {
} }
@Test public void testShouldNotExist() { @Test public void testShouldNotExist() {
var env = new Environment(); var env = new Environment();
assertEquals(env.get(FOO), null); assertEquals(null, env.get(FOO));
assertEquals(env.has(FOO), false); assertEquals(false, env.has(FOO));
} }
@Test public void testShouldAdd() { @Test public void testShouldAdd() {
var env = new Environment(); var env = new Environment();
env.add(FOO, "test"); env.add(FOO, "test");
assertEquals(env.get(FOO), "test"); assertEquals("test", env.get(FOO));
} }
@Test public void testShouldGetFromParent() { @Test public void testShouldGetFromParent() {
var parent = new Environment(); var parent = new Environment();
parent.add(FOO, "test"); parent.add(FOO, "test");
var child = parent.child(); var child = parent.child();
assertEquals(child.get(FOO), "test"); assertEquals("test", child.get(FOO));
assertEquals(child.has(FOO), true); assertEquals(true, child.has(FOO));
} }
@Test public void testShouldHideParent() { @Test public void testShouldHideParent() {
var parent = new Environment(); var parent = new Environment();
parent.add(FOO, "test"); parent.add(FOO, "test");
var child = parent.child(); var child = parent.child();
child.remove(FOO); child.remove(FOO);
assertEquals(child.get(FOO), null); assertEquals(null, child.get(FOO));
assertEquals(child.has(FOO), false); assertEquals(false, child.has(FOO));
} }
@Test public void testShouldAddMarker() { @Test public void testShouldAddMarker() {
var env = new Environment(); var env = new Environment();
env.add(MARKER); env.add(MARKER);
assertEquals(env.has(MARKER), true); assertEquals(true, env.has(MARKER));
assertEquals(env.hasNotNull(MARKER), false); assertEquals(false, env.hasNotNull(MARKER));
} }
@Test public void testShouldInitOnce() { @Test public void testShouldInitOnce() {
var env = new Environment(); var env = new Environment();
assertEquals(env.init(FOO, "a"), "a"); assertEquals("a", env.init(FOO, "a"));
assertEquals(env.init(FOO, "b"), "a"); assertEquals("a", env.init(FOO, "b"));
assertEquals(env.get(FOO), "a"); assertEquals("a", env.get(FOO));
} }
@Test public void testShouldInitOnceFrom() { @Test public void testShouldInitOnceFrom() {
var env = new Environment(); var env = new Environment();
assertEquals(env.initFrom(FOO, () -> "a"), "a"); assertEquals("a", env.initFrom(FOO, () -> "a"));
assertEquals(env.initFrom(FOO, () -> "b"), "a"); assertEquals("a", env.initFrom(FOO, () -> "b"));
assertEquals(env.get(FOO), "a"); assertEquals("a", env.get(FOO));
} }
@Test public void testShouldWrap() { @Test public void testShouldWrap() {
var env = new Environment(); var env = new Environment();
assertEquals(Environment.wrap(env), env); assertEquals(env, Environment.wrap(env));
assertNotEquals(Environment.wrap(null), null); assertInstanceOf(Environment.class, Environment.wrap(null));
} }
} }

View File

@@ -2,8 +2,6 @@ package me.topchetoeu.j2s.common;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import me.topchetoeu.j2s.common.parsing.Filename;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestFilename { public class TestFilename {

View File

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

View File

@@ -1,4 +1,4 @@
package me.topchetoeu.j2s.common.mapping; package me.topchetoeu.j2s.compilation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -13,12 +13,14 @@ import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.FunctionMap;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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 final class CompilationFunctionMap implements 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<>();
@@ -33,6 +35,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;
} }
@@ -43,12 +48,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) {
@@ -75,17 +78,17 @@ public class FunctionMap {
return this; return this;
} }
public FunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) { public CompilationFunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) {
return new FunctionMap(sourceMap, breakpoints, localNames, capturableNames, captureNames); return new CompilationFunctionMap(sourceMap, breakpoints, first, last, localNames, capturableNames, captureNames);
} }
public FunctionMap build(Function<Location, Location> mapper) { public CompilationFunctionMap build() {
return new FunctionMap(sourceMap, breakpoints, new String[0], new String[0], new String[0]); return new CompilationFunctionMap(sourceMap, breakpoints, first, last, new String[0], new String[0], new String[0]);
} }
private FunctionMapBuilder() { } private FunctionMapBuilder() { }
} }
public static final FunctionMap EMPTY = new FunctionMap(); public static final CompilationFunctionMap EMPTY = new CompilationFunctionMap();
private final HashMap<Integer, BreakpointType> bps = new HashMap<>(); private final HashMap<Integer, BreakpointType> bps = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpLocs = new HashMap<>(); private final HashMap<Filename, TreeSet<Location>> bpLocs = new HashMap<>();
@@ -93,28 +96,29 @@ 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) { @Override 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();
} }
public Location toLocation(int pc) { @Override public Location toLocation(int pc) {
return toLocation(pc, false); return toLocation(pc, false);
} }
public BreakpointType getBreakpoint(int pc) { @Override public BreakpointType getBreakpoint(int pc) {
return bps.getOrDefault(pc, BreakpointType.NONE); return bps.getOrDefault(pc, BreakpointType.NONE);
} }
public Location correctBreakpoint(Location loc) { @Override public Location correctBreakpoint(Location loc) {
var set = bpLocs.get(loc.filename()); var set = bpLocs.get(loc.filename());
if (set == null) return null; if (set == null) return null;
else return set.ceiling(loc); else return set.ceiling(loc);
} }
public List<Location> correctBreakpoint(Pattern filename, int line, int column) { @Override public List<Location> correctBreakpoint(Pattern filename, int line, int column) {
var candidates = new HashMap<Filename, TreeSet<Location>>(); var candidates = new HashMap<Filename, TreeSet<Location>>();
for (var name : bpLocs.keySet()) { for (var name : bpLocs.keySet()) {
@@ -132,7 +136,7 @@ public class FunctionMap {
return res; return res;
} }
public List<Location> breakpoints(Location start, Location end) { @Override public List<Location> breakpoints(Location start, Location end) {
if (!Objects.equals(start.filename(), end.filename())) return Arrays.asList(); if (!Objects.equals(start.filename(), end.filename())) return Arrays.asList();
NavigableSet<Location> set = bpLocs.get(start.filename()); NavigableSet<Location> set = bpLocs.get(start.filename());
if (set == null) return Arrays.asList(); if (set == null) return Arrays.asList();
@@ -152,8 +156,25 @@ public class FunctionMap {
return pcToLoc.lastEntry().getValue(); return pcToLoc.lastEntry().getValue();
} }
public FunctionMap clone() { @Override public Location first() {
var res = new FunctionMap(new HashMap<>(), new HashMap<>(), localNames, capturableNames, captureNames); return first;
}
@Override public Location last() {
return last;
}
@Override public String[] capturableNames() {
return capturableNames;
}
@Override public String[] captureNames() {
return captureNames;
}
@Override public String[] localNames() {
return localNames;
}
public CompilationFunctionMap clone() {
var res = new CompilationFunctionMap(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);
@@ -161,7 +182,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 CompilationFunctionMap(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()) {
@@ -180,11 +201,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 CompilationFunctionMap() {
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

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

View File

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

View File

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

View File

@@ -3,8 +3,8 @@ package me.topchetoeu.j2s.compilation;
import java.util.List; import java.util.List;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.scope.Variable;
import me.topchetoeu.j2s.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;

View File

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

View File

@@ -6,13 +6,10 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; 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.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.BreakNode;
import me.topchetoeu.j2s.compilation.control.ContinueNode; import me.topchetoeu.j2s.compilation.control.ContinueNode;
import me.topchetoeu.j2s.compilation.control.DebugNode; 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.ThrowNode;
import me.topchetoeu.j2s.compilation.control.TryNode; import me.topchetoeu.j2s.compilation.control.TryNode;
import me.topchetoeu.j2s.compilation.control.WhileNode; 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.scope.FunctionScope;
import me.topchetoeu.j2s.compilation.values.ArgumentsNode; import me.topchetoeu.j2s.compilation.values.ArgumentsNode;
import me.topchetoeu.j2s.compilation.values.ArrayNode; import me.topchetoeu.j2s.compilation.values.ArrayNode;

View File

@@ -5,11 +5,11 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.Instruction; 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.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 class LabelContext {
public static final Key<LabelContext> BREAK_CTX = new Key<>(); public static final Key<LabelContext> BREAK_CTX = new Key<>();

View File

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

View File

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

View File

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

View File

@@ -1,15 +1,15 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.SyntaxException; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class BreakNode extends Node {
public final String label; public final String label;

View File

@@ -1,15 +1,15 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.SyntaxException; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class ContinueNode extends Node {
public final String label; public final String label;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 { public class DebugNode extends Node {
@Override public void compileFunctions(CompileResult target) { @Override public void compileFunctions(CompileResult target) {

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.VariableNode;
import me.topchetoeu.j2s.compilation.values.constants.BoolNode; import me.topchetoeu.j2s.compilation.values.constants.BoolNode;
import me.topchetoeu.j2s.compilation.values.operations.IndexNode; import me.topchetoeu.j2s.compilation.values.operations.IndexNode;

View File

@@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class DoWhileNode extends Node {
public final Node condition, body; public final Node condition, body;

View File

@@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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.VariableNode;
public class ForInNode extends Node { public class ForInNode extends Node {
@@ -31,13 +31,18 @@ public class ForInNode extends Node {
body.compileFunctions(target); body.compileFunctions(target);
} }
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
target.add(Instruction.loadIntrinsics("keys"));
object.compile(target, true, BreakpointType.STEP_OVER); object.compile(target, true, BreakpointType.STEP_OVER);
target.add(Instruction.keys(false, true)); target.add(Instruction.pushValue(false));
target.add(Instruction.pushValue(true));
target.add(Instruction.call(3, false));
int start = target.size(); int start = target.size();
target.add(Instruction.dup()); target.add(Instruction.dup());
target.add(Instruction.call(0, false));
target.add(Instruction.dup());
target.add(Instruction.loadMember("done"));
int mid = target.temp(); int mid = target.temp();
target.add(Instruction.loadMember("value")).setLocation(binding.loc()); target.add(Instruction.loadMember("value")).setLocation(binding.loc());
target.add(VariableNode.toSet(target, loc(), binding.name, false, true)).setLocation(binding.loc()); target.add(VariableNode.toSet(target, loc(), binding.name, false, true)).setLocation(binding.loc());
@@ -52,7 +57,7 @@ public class ForInNode extends Node {
target.add(Instruction.jmp(start - endI)); target.add(Instruction.jmp(start - endI));
target.add(Instruction.discard()); target.add(Instruction.discard());
target.set(mid, Instruction.jmpIfNot(endI - mid + 1)); target.set(mid, Instruction.jmpIf(endI - mid + 1));
end.set(endI + 1); end.set(endI + 1);
LabelContext.popLoop(target.env, label); LabelContext.popLoop(target.env, label);

View File

@@ -1,17 +1,17 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.VariableDeclareNode; 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 class ForNode extends Node {
public final Node declaration, assignment, condition, body; public final Node declaration, assignment, condition, body;

View File

@@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class IfNode extends Node {
public final Node condition, body, elseBody; public final Node condition, body, elseBody;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 class ReturnNode extends Node {
public final Node value; public final Node value;

View File

@@ -4,17 +4,17 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class SwitchNode extends Node {
public static class SwitchCase { public static class SwitchCase {

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 class ThrowNode extends Node {
public final Node value; public final Node value;

View File

@@ -1,17 +1,17 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.CompoundNode; import me.topchetoeu.j2s.compilation.CompoundNode;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class TryNode extends Node {
public final CompoundNode tryBody; public final CompoundNode tryBody;

View File

@@ -1,16 +1,16 @@
package me.topchetoeu.j2s.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.LabelContext; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.j2s.compilation.Node; 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 class WhileNode extends Node {
public final Node condition, body; 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.HashMap;
import java.util.stream.Collectors; 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.Metadata;
import me.topchetoeu.j2s.common.StringifyUtils;
import me.topchetoeu.j2s.common.SyntaxException; import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Filename; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
public class JSON { public class JSON {
public static ParseRes<JSONElement> parseString(Source src, int i) { public static ParseRes<JSONElement> parseString(Source src, int i) {
@@ -110,37 +110,10 @@ public class JSON {
} }
public static String stringify(JSONElement el) { public static String stringify(JSONElement el) {
if (el.isNumber()) { if (el.isNumber()) return StringifyUtils.quoteNumber(el.number());
var d = el.number(); if (el.isString()) return StringifyUtils.quoteString(el.string());
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.isBoolean()) return el.bool() ? "true" : "false"; if (el.isBoolean()) return el.bool() ? "true" : "false";
if (el.isNull()) return "null"; 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()) { if (el.isList()) {
var res = new StringBuilder().append("["); var res = new StringBuilder().append("[");
for (int i = 0; i < el.list().size(); i++) { for (int i = 0; i < el.list().size(); i++) {
@@ -156,7 +129,7 @@ public class JSON {
for (int i = 0; i < entries.size(); i++) { for (int i = 0; i < entries.size(); i++) {
if (i != 0) res.append(","); 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(":");
res.append(stringify(entries.get(i).getValue())); 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 class JSONElement {
public static enum Type { 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.ArrayList;
import java.util.Arrays; 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.Collection;
import java.util.HashMap; import java.util.HashMap;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.members; package me.topchetoeu.j2s.compilation.members;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.ObjectNode;
public class FieldMemberNode implements Member { public class FieldMemberNode implements Member {

View File

@@ -1,6 +1,6 @@
package me.topchetoeu.j2s.compilation.members; 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; import me.topchetoeu.j2s.compilation.CompileResult;
public interface Member { public interface Member {

View File

@@ -3,16 +3,16 @@ package me.topchetoeu.j2s.compilation.members;
import java.util.Arrays; import java.util.Arrays;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.CompoundNode; import me.topchetoeu.j2s.compilation.CompoundNode;
import me.topchetoeu.j2s.compilation.FunctionNode; import me.topchetoeu.j2s.compilation.FunctionNode;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.ObjectNode;
import me.topchetoeu.j2s.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;
@@ -38,11 +38,20 @@ public final class PropertyMemberNode extends FunctionNode implements Member {
} }
@Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) { @Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) {
if (pollute) target.add(Instruction.dup()); if (isGetter()) {
key.compile(target, true); target.add(Instruction.loadIntrinsics("defGetter"));
}
else {
target.add(Instruction.loadIntrinsics("defSetter"));
}
target.add(Instruction.dup(1, 1));
key.compile(target, true);
target.add(Instruction.loadFunc(target.childrenIndices.get(this), name(name), captures(target))).setLocation(loc()); target.add(Instruction.loadFunc(target.childrenIndices.get(this), name(name), captures(target))).setLocation(loc());
target.add(Instruction.defProp(isSetter())); target.add(Instruction.call(3, false));
target.add(Instruction.discard());
if (!pollute) target.add(Instruction.discard());
} }
public PropertyMemberNode(Location loc, Location end, Node key, VariableNode argument, CompoundNode body) { public PropertyMemberNode(Location loc, Location end, Node key, VariableNode argument, CompoundNode body) {

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

View File

@@ -1,6 +1,4 @@
package me.topchetoeu.j2s.common.parsing; package me.topchetoeu.j2s.compilation.parsing;
import me.topchetoeu.j2s.common.SyntaxException;
public class Parsing { public class Parsing {
public static boolean isDigit(Character c) { public static boolean isDigit(Character c) {
@@ -18,14 +16,13 @@ public class Parsing {
} }
public static int skipEmpty(Source src, int i) { 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; int n = 0;
if (i == 0 && src.is(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++; n++;
} }
@@ -88,7 +85,7 @@ public class Parsing {
if (i + n >= src.size()) return ParseRes.error(src.loc(i), "Invalid hexadecimal escape sequence"); if (i + n >= src.size()) return ParseRes.error(src.loc(i), "Invalid hexadecimal escape sequence");
int val = fromHex(src.at(i + n)); 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++; n++;
newC = (newC << 4) | val; 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"); if (i + n >= src.size()) return ParseRes.error(src.loc(i), "Invalid Unicode escape sequence");
int val = fromHex(src.at(i + n)); 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++; n++;
newC = (newC << 4) | val; 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 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 class Source {
public final Environment env; public final Environment env;

View File

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

View File

@@ -1,6 +1,6 @@
package me.topchetoeu.j2s.compilation.patterns; 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; import me.topchetoeu.j2s.compilation.CompileResult;
/** /**

View File

@@ -32,7 +32,7 @@ public final class FunctionScope {
} }
/** /**
* @returns If a variable with the same name exists, the old variable. Otherwise, the given variable * @return If a variable with the same name exists, the old variable. Otherwise, the given variable
*/ */
public Variable define(Variable var) { public Variable define(Variable var) {
if (passthrough) return null; if (passthrough) return null;
@@ -48,7 +48,7 @@ public final class FunctionScope {
} }
/** /**
* @returns A variable with the given name, or null if a global variable * @return A variable with the given name, or null if a global variable
*/ */
public Variable define(String name) { public Variable define(String name) {
return define(new Variable(name, false)); return define(new Variable(name, false));

View File

@@ -39,9 +39,9 @@ public final class VariableIndex {
} }
public final Instruction toSet(boolean keep) { public final Instruction toSet(boolean keep) {
switch (type) { switch (type) {
case CAPTURES: return Instruction.storeVar(~index, keep, false); case CAPTURES: return Instruction.storeVar(~index, keep);
case CAPTURABLES: return Instruction.storeVar(index, keep, false); case CAPTURABLES: return Instruction.storeVar(index, keep);
case LOCALS: return Instruction.storeVar(index, keep, false); case LOCALS: return Instruction.storeVar(index, keep);
default: throw new UnsupportedOperationException("Unknown index type " + type); default: throw new UnsupportedOperationException("Unknown index type " + type);
} }
} }

View File

@@ -175,7 +175,7 @@ public final class VariableList implements Iterable<Variable> {
this.offset = () -> offset; this.offset = () -> offset;
} }
/** /**
* @param offset Will offset the indices by the size of the given list * @param prev Will offset the indices by the size of the given list
*/ */
public VariableList(IndexType type, VariableList prev) { public VariableList(IndexType type, VariableList prev) {
this.indexType = type; this.indexType = type;

View File

@@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;

View File

@@ -3,13 +3,13 @@ package me.topchetoeu.j2s.compilation.values;
import java.util.ArrayList; import java.util.ArrayList;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 { public class ArrayNode extends Node {

View File

@@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;

View File

@@ -4,16 +4,16 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.members.FieldMemberNode; import me.topchetoeu.j2s.compilation.members.FieldMemberNode;
import me.topchetoeu.j2s.compilation.members.Member; import me.topchetoeu.j2s.compilation.members.Member;
import me.topchetoeu.j2s.compilation.members.PropertyMemberNode; 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.NumberNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;

View File

@@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; 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 class RegexNode extends Node {
public final String pattern, flags; public final String pattern, flags;
@@ -15,7 +15,10 @@ public class RegexNode extends Node {
} }
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
target.add(Instruction.loadRegex(pattern, flags)); target.add(Instruction.loadIntrinsics("regex"));
target.add(Instruction.pushValue(pattern));
target.add(Instruction.pushValue(flags));
target.add(Instruction.call(2, false));
if (!pollute) target.add(Instruction.discard()); if (!pollute) target.add(Instruction.discard());
} }

View File

@@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.patterns.ChangeTarget;
public class VariableNode extends Node implements ChangeTarget { public class VariableNode extends Node implements ChangeTarget {

View File

@@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;

View File

@@ -1,7 +1,7 @@
package me.topchetoeu.j2s.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;

View File

@@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; 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 class NumberNode extends Node {
public final double value; public final double value;

View File

@@ -1,12 +1,12 @@
package me.topchetoeu.j2s.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; 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 class StringNode extends Node {
public final String value; public final String value;

View File

@@ -1,9 +1,9 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.SyntaxException; import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.j2s.compilation.patterns.AssignTarget; 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 java.util.ArrayList;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 class CallNode extends Node {
public final Node func; public final Node func;

View File

@@ -1,14 +1,14 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 { public class DiscardNode extends Node {

View File

@@ -1,14 +1,14 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.j2s.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 class LazyAndNode extends Node {
public final Node first, second; public final Node first, second;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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 { public class LazyOrNode extends Node {

View File

@@ -6,14 +6,14 @@ import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; 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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.AssignTargetLike;
import me.topchetoeu.j2s.compilation.patterns.ChangeTarget; import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;

View File

@@ -1,13 +1,13 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; 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.CompileResult;
import me.topchetoeu.j2s.compilation.Node; 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.patterns.ChangeTarget;
import me.topchetoeu.j2s.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;

View File

@@ -1,13 +1,14 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.parsing.ParseRes; import me.topchetoeu.j2s.common.Operation;
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.CompileResult;
import me.topchetoeu.j2s.compilation.JavaScript; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.j2s.compilation.Node; 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.VariableNode;
public class TypeofNode extends Node { public class TypeofNode extends Node {
@@ -20,14 +21,14 @@ public class TypeofNode extends Node {
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
if (value instanceof VariableNode varNode) { if (value instanceof VariableNode varNode) {
target.add(VariableNode.toGet(target, varNode.loc(), varNode.name, true, true)); target.add(VariableNode.toGet(target, varNode.loc(), varNode.name, true, true));
if (pollute) target.add(Instruction.typeof()); if (pollute) target.add(Instruction.operation(Operation.TYPEOF));
else target.add(Instruction.discard()); else target.add(Instruction.discard());
return; return;
} }
value.compile(target, pollute); value.compile(target, pollute);
if (pollute) target.add(Instruction.typeof()); if (pollute) target.add(Instruction.operation(Operation.TYPEOF));
} }
public TypeofNode(Location loc, Node value) { public TypeofNode(Location loc, Node value) {

View File

@@ -1,8 +1,8 @@
package me.topchetoeu.j2s.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.j2s.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Operation; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.j2s.compilation.FunctionNode; import me.topchetoeu.j2s.compilation.FunctionNode;
import me.topchetoeu.j2s.compilation.Node; 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,65 @@
package me.topchetoeu.j2s.compilation.parsing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
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,48 @@
package me.topchetoeu.j2s.compilation.parsing;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
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,4 +1,4 @@
project_group = me.topchetoeu project_group = me.topchetoeu.j2s
project_name = j2s project_name = j2s
project_version = 0.10.4-beta project_version = 0.10.7-beta
main_class = me.topchetoeu.j2s.repl.SimpleRepl main_class = me.topchetoeu.j2s.repl.SimpleRepl

View File

@@ -10,6 +10,8 @@ declare interface String {
charCodeAt(i: number): number; charCodeAt(i: number): number;
codePointAt(i: number): number; codePointAt(i: number): number;
startsWith(search: string): boolean;
endsWith(search: string): boolean;
includes(search: string, offset?: number): number; includes(search: string, offset?: number): number;
indexOf(search: string, offset?: number): number; indexOf(search: string, offset?: number): number;
lastIndexOf(search: string, offset?: number): number; lastIndexOf(search: string, offset?: number): number;

View File

@@ -1,4 +1,4 @@
import { object, setGlobalPrototypes, target } from "./primordials.ts"; import { object, setGlobalPrototypes, setIntrinsic, target } from "./primordials.ts";
import { Error, RangeError, SyntaxError, TypeError } from "./values/errors.ts"; import { Error, RangeError, SyntaxError, TypeError } from "./values/errors.ts";
import { Boolean } from "./values/boolean.ts"; import { Boolean } from "./values/boolean.ts";
import { Function } from "./values/function.ts"; import { Function } from "./values/function.ts";
@@ -87,5 +87,20 @@ setGlobalPrototypes({
type: TypeError.prototype, type: TypeError.prototype,
uint8: Uint8Array.prototype, uint8: Uint8Array.prototype,
int32: Int32Array.prototype, int32: Int32Array.prototype,
regex: RegExp,
}); });
setIntrinsic("regex", RegExp);
setIntrinsic("keys", (obj: object, own: boolean, onlyEnumerable: boolean) => {
const members = object.getMembers(obj, own, onlyEnumerable);
let i = 0;
return () => {
if (i >= members.length) return { done: true };
else return { value: members[i++] };
};
});
setIntrinsic("defGetter", (obj: object, key: any, func: Function) => {
object.defineProperty(obj, key, { g: func, e: true, c: true });
});
setIntrinsic("defSetter", (obj: object, key: any, func: Function) => {
object.defineProperty(obj, key, { s: func, e: true, c: true });
});

View File

@@ -39,8 +39,8 @@ export interface ObjectPrimordials {
defineProperty(obj: object, key: string | number | symbol, conf: { g?: Function, s?: Function, e?: boolean, c?: boolean }): boolean; defineProperty(obj: object, key: string | number | symbol, conf: { g?: Function, s?: Function, e?: boolean, c?: boolean }): boolean;
defineField(obj: object, key: string | number | symbol, conf: { v?: any, e?: boolean, c?: boolean, w?: boolean }): boolean; defineField(obj: object, key: string | number | symbol, conf: { v?: any, e?: boolean, c?: boolean, w?: boolean }): boolean;
getOwnMember(obj: object, key: any): PropertyDescriptor | undefined; getOwnMember(obj: object, key: any): PropertyDescriptor | undefined;
getOwnMembers(obj: object, onlyEnumerable: boolean): string[]; getMembers(obj: object, own: boolean, onlyEnumerable: boolean): string[];
getOwnSymbolMembers(obj: object, onlyEnumerable: boolean): symbol[]; getSymbolMembers(obj: object, own: boolean, onlyEnumerable: boolean): symbol[];
getPrototype(obj: object): object | undefined; getPrototype(obj: object): object | undefined;
setPrototype(obj: object, proto?: object): object; setPrototype(obj: object, proto?: object): object;
preventExt(obj: object): void; preventExt(obj: object): void;
@@ -72,7 +72,7 @@ export interface BufferPrimordials {
export interface FunctionPrimordials { export interface FunctionPrimordials {
invokeType(args: IArguments, self: any): "new" | "call"; invokeType(args: IArguments, self: any): "new" | "call";
invokeTypeInfer(): "new" | "call"; invokeTypeInfer(): "new" | "call";
target(): Function | null | undefined; target(level?: number): Function | null | undefined;
setConstructable(func: Function, flag: boolean): void; setConstructable(func: Function, flag: boolean): void;
setCallable(func: Function, flag: boolean): void; setCallable(func: Function, flag: boolean): void;
invoke(func: Function, self: any, args: any[]): any; invoke(func: Function, self: any, args: any[]): any;
@@ -105,11 +105,12 @@ export interface Primordials {
exec(target: string, offset: number, indices: boolean): { matches: RegExpMatchArray, end: number } | null; exec(target: string, offset: number, indices: boolean): { matches: RegExpMatchArray, end: number } | null;
groupCount(): number; groupCount(): number;
}; };
compile(src: string): Function; compile(src: string, filename?: string): Function;
setGlobalPrototypes(prototype: Record<string, any>): void; setGlobalPrototypes(prototype: Record<string, any>): void;
now(): number; now(): number;
next(func: () => void): void; next(func: () => void): void;
schedule(func: () => void, delay: number): () => void; schedule(func: () => void, delay: number): () => void;
setIntrinsic(key: string, val: any): void;
} }
// prevent optimization to "undefined", which doesn't exist yet // prevent optimization to "undefined", which doesn't exist yet
@@ -132,6 +133,7 @@ export const {
now, now,
next, next,
schedule, schedule,
setIntrinsic,
} = primordials; } = primordials;
export type regex = InstanceType<typeof regex>; export type regex = InstanceType<typeof regex>;

View File

@@ -55,23 +55,12 @@ export const Function = (() => {
return res; return res;
} }
public static compile(src = "", { globals = [], wrap = false }: { globals?: string[], wrap?: boolean } = {}) { public static compile(src: string, filename?: string) {
const parts = []; return compile(String(src), filename);
}
if (wrap) parts[parts.length] = "return (function() {\n"; public static newTarget() {
if (globals.length > 0) { return func.target(1);
parts[parts.length] = "let {";
for (let i = 0; i < globals.length; i++) {
if (i > 0) parts[parts.length] = ",";
parts[parts.length] = globals[i];
}
parts[parts.length] = "} = arguments[0];";
}
parts[parts.length] = src;
if (wrap) parts[parts.length] = "\n})(arguments[0])";
const res = compile(string.stringBuild(parts));
return res;
} }
} }

View File

@@ -55,10 +55,10 @@ export const Object = (() => {
return object.getOwnMember(obj, key); return object.getOwnMember(obj, key);
} }
public static getOwnPropertyNames(obj: object): string[] { public static getOwnPropertyNames(obj: object): string[] {
return object.getOwnMembers(obj, false); return object.getMembers(obj, true, false);
} }
public static getOwnPropertySymbols(obj: object): symbol[] { public static getOwnPropertySymbols(obj: object): symbol[] {
return object.getOwnSymbolMembers(obj, false); return object.getSymbolMembers(obj, true, false);
} }
public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) { public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) {
@@ -98,8 +98,8 @@ export const Object = (() => {
return obj; return obj;
} }
public static defineProperties(obj: object, desc: PropertyDescriptorMap) { public static defineProperties(obj: object, desc: PropertyDescriptorMap) {
const keys = object.getOwnMembers(desc, true) as ((keyof typeof obj) & string)[]; const keys = object.getMembers(desc, true, true) as ((keyof typeof obj) & string)[];
const symbols = object.getOwnSymbolMembers(desc, true) as ((keyof typeof obj) & symbol)[]; const symbols = object.getSymbolMembers(desc, true, true) as ((keyof typeof obj) & symbol)[];
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
Object.defineProperty(obj, keys[i], desc[keys[i]]); Object.defineProperty(obj, keys[i], desc[keys[i]]);
@@ -119,8 +119,8 @@ export const Object = (() => {
public static assign(target: any) { public static assign(target: any) {
for (let i = 1; i < arguments.length; i++) { for (let i = 1; i < arguments.length; i++) {
const obj = arguments[i]; const obj = arguments[i];
const keys = object.getOwnMembers(obj, false); const keys = object.getMembers(obj, true, false);
const symbols = object.getOwnSymbolMembers(obj, false); const symbols = object.getSymbolMembers(obj, true, false);
for (let j = 0; j < keys.length; j++) { for (let j = 0; j < keys.length; j++) {
target[keys[j]] = obj[keys[j]]; target[keys[j]] = obj[keys[j]];
@@ -142,8 +142,8 @@ export const Object = (() => {
public static keys(obj: any) { public static keys(obj: any) {
const res: any[] = []; const res: any[] = [];
const keys = object.getOwnMembers(obj, true); const keys = object.getMembers(obj, true, true);
const symbols = object.getOwnSymbolMembers(obj, true); const symbols = object.getSymbolMembers(obj, true, true);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
res[res.length] = keys[i]; res[res.length] = keys[i];
@@ -156,8 +156,8 @@ export const Object = (() => {
} }
public static values(obj: any) { public static values(obj: any) {
const res: any[] = []; const res: any[] = [];
const keys = object.getOwnMembers(obj, true); const keys = object.getMembers(obj, true, true);
const symbols = object.getOwnSymbolMembers(obj, true); const symbols = object.getSymbolMembers(obj, true, true);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
res[res.length] = obj[keys[i]]; res[res.length] = obj[keys[i]];
@@ -170,8 +170,8 @@ export const Object = (() => {
} }
public static entries(obj: any) { public static entries(obj: any) {
const res: [any, any][] = []; const res: [any, any][] = [];
const keys = object.getOwnMembers(obj, true); const keys = object.getMembers(obj, true, true);
const symbols = object.getOwnSymbolMembers(obj, true); const symbols = object.getSymbolMembers(obj, true, true);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
res[res.length] = [keys[i], obj[keys[i]]]; res[res.length] = [keys[i], obj[keys[i]]];

View File

@@ -1,4 +1,3 @@
import coffeescript from "./coffeescript.ts";
import babel from "./babel.ts"; import babel from "./babel.ts";
register(v => coffeescript(babel(v))); register(babel);

View File

@@ -1,5 +1,5 @@
import { SourceMap } from "./map.ts"; import { SourceMap } from "./map.ts";
import { transform, availablePresets } from "@babel/standalone"; import { transform, availablePlugins } from "@babel/standalone";
export default function babel(next: Compiler): Compiler { export default function babel(next: Compiler): Compiler {
print("Loaded babel!"); print("Loaded babel!");
@@ -8,7 +8,64 @@ export default function babel(next: Compiler): Compiler {
const res = transform(code, { const res = transform(code, {
filename, filename,
sourceMaps: true, sourceMaps: true,
presets: [availablePresets.env], assumptions: {
arrayLikeIsIterable: true,
constantSuper: true,
ignoreFunctionLength: true,
ignoreToPrimitiveHint: true,
mutableTemplateObject: true,
noDocumentAll: true,
noNewArrows: true,
noUninitializedPrivateFieldAccess: true,
privateFieldsAsSymbols: true,
},
plugins: [
// ES2022
availablePlugins["transform-class-properties"],
availablePlugins["transform-class-static-block"],
availablePlugins["transform-private-methods"],
availablePlugins["transform-private-property-in-object"],
// "syntax-top-level-await",
// ES2021
availablePlugins["transform-logical-assignment-operators"],
availablePlugins["transform-numeric-separator"],
// ES2020
availablePlugins["transform-optional-chaining"],
availablePlugins["transform-nullish-coalescing-operator"],
// ES2018
availablePlugins["transform-async-generator-functions"],
availablePlugins["transform-object-rest-spread"],
availablePlugins["transform-unicode-property-regex"],
// ES2017
availablePlugins["transform-async-to-generator"],
// ES2016
availablePlugins["transform-exponentiation-operator"],
// ES2015
availablePlugins["transform-arrow-functions"],
availablePlugins["transform-block-scoping"],
availablePlugins["transform-classes"],
availablePlugins["transform-computed-properties"],
availablePlugins["transform-destructuring"],
availablePlugins["transform-duplicate-keys"],
availablePlugins["transform-for-of"],
availablePlugins["transform-function-name"],
availablePlugins["transform-literals"],
availablePlugins["transform-new-target"],
availablePlugins["transform-object-super"],
availablePlugins["transform-parameters"],
availablePlugins["transform-shorthand-properties"],
availablePlugins["transform-spread"],
availablePlugins["transform-sticky-regex"],
availablePlugins["transform-template-literals"],
availablePlugins["transform-unicode-escapes"],
availablePlugins["transform-unicode-regex"],
],
}); });
const map = SourceMap.parse({ const map = SourceMap.parse({
@@ -18,7 +75,9 @@ export default function babel(next: Compiler): Compiler {
}); });
registerSource(filename, code); registerSource(filename, code);
return next("babel-internal://" + filename, res.code!, SourceMap.chain(map, prevMap)); const func = next("babel-internal://" + filename, res.code!, SourceMap.chain(map, prevMap));
func.name = filename;
return func;
}; };
} }

View File

@@ -21,7 +21,9 @@ export default function coffee(next: Compiler): Compiler {
}); });
registerSource(filename, code); registerSource(filename, code);
return next("coffee-internal://" + filename, result, SourceMap.chain(map, prevMap)); const func = next("coffee-internal://" + filename, result, SourceMap.chain(map, prevMap));
func.name = filename;
return func;
}; };
} }

View File

@@ -109,10 +109,12 @@ export default function typescript(next: Compiler): Compiler {
registerSource(filename, code); registerSource(filename, code);
const compiled = next("ts-internal://" + filename, result, SourceMap.chain(map, prevMap)); const compiled = next("ts-internal://" + filename, result, SourceMap.chain(map, prevMap));
return function (this: any) { const func = function (this: any) {
const res = compiled.apply(this, arguments); const res = compiled.apply(this, arguments);
if (declaration !== '') files["/src." + declI++ + ".d.ts"] = ScriptSnapshot.fromString(declaration); if (declaration !== '') files["/src." + declI++ + ".d.ts"] = ScriptSnapshot.fromString(declaration);
return res; return res;
}; };
func.name = filename;
return func;
}; };
} }

View File

@@ -1,17 +1,17 @@
{ {
"include": ["**/*.ts"], "include": ["**/*.ts"],
"compilerOptions": { "compilerOptions": {
"strict": true, "strict": true,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"moduleResolution": "Bundler", "moduleResolution": "Bundler",
"module": "ESNext", "module": "ESNext",
"target": "ESNext", "target": "ESNext",
"noLib": true, "noLib": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"noEmit": true "noEmit": true
} }
} }

View File

@@ -1,12 +1,12 @@
package me.topchetoeu.j2s.runtime; package me.topchetoeu.j2s.repl;
import java.util.HashSet; import java.util.HashSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.environment.Environment; import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.common.json.JSONElement; import me.topchetoeu.j2s.compilation.json.JSONElement;
import me.topchetoeu.j2s.common.json.JSONList; import me.topchetoeu.j2s.compilation.json.JSONList;
import me.topchetoeu.j2s.common.json.JSONMap; import me.topchetoeu.j2s.compilation.json.JSONMap;
import me.topchetoeu.j2s.runtime.exceptions.EngineException; import me.topchetoeu.j2s.runtime.exceptions.EngineException;
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.ArrayValue;

View File

@@ -16,14 +16,21 @@ import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; 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.Metadata;
import me.topchetoeu.j2s.common.Reading; import me.topchetoeu.j2s.common.Reading;
import me.topchetoeu.j2s.common.SyntaxException; 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.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.SimpleDebugHandler;
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;
@@ -33,8 +40,7 @@ import me.topchetoeu.j2s.runtime.Compiler;
import me.topchetoeu.j2s.runtime.Engine; import me.topchetoeu.j2s.runtime.Engine;
import me.topchetoeu.j2s.runtime.EventLoop; import me.topchetoeu.j2s.runtime.EventLoop;
import me.topchetoeu.j2s.runtime.Frame; import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.JSONConverter; import me.topchetoeu.j2s.runtime.debug.DebugHandler;
import me.topchetoeu.j2s.runtime.debug.DebugContext;
import me.topchetoeu.j2s.runtime.exceptions.EngineException; import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value; import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.functions.CodeFunction; import me.topchetoeu.j2s.runtime.values.functions.CodeFunction;
@@ -43,10 +49,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;
@@ -60,9 +62,9 @@ public class SimpleRepl {
var res = JavaScript.compile(env, filename, raw, true); var res = JavaScript.compile(env, filename, raw, true);
var body = res.body(); var body = res.body();
DebugContext.get(env).onSource(filename, raw); DebugHandler.get(env).onSourceLoad(filename, raw);
for (var el : res.bodies()) { for (var el : res.all()) {
DebugContext.get(env).onFunctionLoad(el, res.map(mapper)); DebugHandler.get(env).onFunctionLoad(el.body(), el.map(mapper));
} }
return new CodeFunction(env, filename.toString(), body, new Value[0][]); return new CodeFunction(env, filename.toString(), body, new Value[0][]);
@@ -97,8 +99,8 @@ public class SimpleRepl {
server = new DebugServer(); server = new DebugServer();
debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true); debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true);
server.targets.put("default", (socket, req) -> new SimpleDebugger(socket) server.targets.put("default", (socket, req) -> new SimpleDebugger(socket)
.attach(DebugContext.get(environment)) .attach((SimpleDebugHandler)DebugHandler.get(environment))
.attach(DebugContext.get(tsEnvironment)) .attach((SimpleDebugHandler)DebugHandler.get(tsEnvironment))
); );
try { try {
@@ -385,13 +387,29 @@ public class SimpleRepl {
if (num.isInt()) return num; if (num.isInt()) return num;
else return NumberValue.of(num.getDouble() - num.getDouble() % 1); 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 -> { res.defineOwnField(env, "parseFloat", new NativeFunction(args -> {
if (args.get(0) instanceof NumberValue) { if (args.get(0) instanceof NumberValue) {
return args.get(0); 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()))); res.defineOwnField(env, "isNaN", new NativeFunction(args -> BoolValue.of(args.get(0).isNaN())));
@@ -528,17 +546,17 @@ public class SimpleRepl {
args.get(0).setPrototype(env, proto); args.get(0).setPrototype(env, proto);
return args.get(0); return args.get(0);
})); }));
res.defineOwnField(env, "getOwnMembers", new NativeFunction(args -> { res.defineOwnField(env, "getMembers", new NativeFunction(args -> {
var val = new ArrayValue(); var val = new ArrayValue();
for (var key : args.get(0).getOwnMembers(env, args.get(1).toBoolean())) { for (var key : args.get(0).getMembers(env, args.get(1).toBoolean(), args.get(2).toBoolean())) {
val.set(args.env, val.size(), StringValue.of(key)); val.set(args.env, val.size(), StringValue.of(key));
} }
return val; return val;
})); }));
res.defineOwnField(env, "getOwnSymbolMembers", new NativeFunction(args -> { res.defineOwnField(env, "getSymbolMembers", new NativeFunction(args -> {
return ArrayValue.of(args.get(0).getOwnSymbolMembers(env, args.get(1).toBoolean())); return ArrayValue.of(args.get(0).getSymbolMembers(env, args.get(1).toBoolean(), args.get(2).toBoolean()));
})); }));
res.defineOwnField(env, "getOwnMember", new NativeFunction(args -> { res.defineOwnField(env, "getOwnMember", new NativeFunction(args -> {
var obj = args.get(0); var obj = args.get(0);
@@ -684,14 +702,14 @@ 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());
})); }));
res.defineOwnField(env, "construct", new NativeFunction(args -> { res.defineOwnField(env, "construct", new NativeFunction(args -> {
var func = (FunctionValue)args.get(0); var func = (FunctionValue)args.get(0);
var target = args.get(1); 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()); if (target == Value.UNDEFINED) return func.constructNoSelf(env, funcArgs.toArray());
else return func.construct(env, target, funcArgs.toArray()); else return func.construct(env, target, funcArgs.toArray());
@@ -758,22 +776,23 @@ public class SimpleRepl {
setProto(args.env, env, Value.RANGE_ERR_PROTO, obj, "range"); setProto(args.env, env, Value.RANGE_ERR_PROTO, obj, "range");
setProto(args.env, env, Value.UINT8_ARR_PROTO, obj, "uint8"); setProto(args.env, env, Value.UINT8_ARR_PROTO, obj, "uint8");
setProto(args.env, env, Value.INT32_ARR_PROTO, obj, "int32"); setProto(args.env, env, Value.INT32_ARR_PROTO, obj, "int32");
var val = obj.getMember(args.env, "regex");
if (val instanceof FunctionValue func) {
env.add(Value.REGEX_CONSTR, func);
}
return Value.UNDEFINED; return Value.UNDEFINED;
})); }));
res.defineOwnField(env, "setIntrinsic", new NativeFunction(args -> { res.defineOwnField(env, "setIntrinsic", new NativeFunction(args -> {
var name = args.get(0).toString(env); var name = args.get(0).toString(env);
var val = args.get(1); var val = args.get(1);
Value.intrinsics(environment).put(name, val); Value.intrinsics(env).put(name, val);
return Value.UNDEFINED; return Value.UNDEFINED;
})); }));
res.defineOwnField(env, "compile", new NativeFunction(args -> { res.defineOwnField(env, "compile", new NativeFunction(args -> {
return Compiler.compileFunc(env, new Filename(Metadata.name(), "func" + i[0]++ + ".js"), args.get(0).toString(env)); var nameVal = args.get(1);
var name = nameVal instanceof VoidValue ?
new Filename(Metadata.name(), "func" + i[0]++ + ".js") :
Filename.parse(nameVal.toString(args.env));
return Compiler.compileFunc(env, name, args.get(0).toString(env));
})); }));
res.defineOwnField(env, "now", new NativeFunction(args -> { res.defineOwnField(env, "now", new NativeFunction(args -> {
return NumberValue.of(System.currentTimeMillis()); return NumberValue.of(System.currentTimeMillis());
@@ -828,7 +847,7 @@ public class SimpleRepl {
private static Environment initEnv() { private static Environment initEnv() {
var env = new Environment(); var env = new Environment();
env.add(EventLoop.KEY, engine); env.add(EventLoop.KEY, engine);
env.add(DebugContext.KEY, new DebugContext()); env.add(DebugHandler.KEY, new SimpleDebugHandler());
env.add(Compiler.KEY, DEFAULT_COMPILER); env.add(Compiler.KEY, DEFAULT_COMPILER);
// env.add(CompileResult.DEBUG_LOG); // env.add(CompileResult.DEBUG_LOG);
@@ -887,7 +906,7 @@ public class SimpleRepl {
tsGlob.defineOwnField(tsEnvironment, "registerSource", new NativeFunction(args -> { tsGlob.defineOwnField(tsEnvironment, "registerSource", new NativeFunction(args -> {
var filename = Filename.parse(args.get(0).toString(args.env)); var filename = Filename.parse(args.get(0).toString(args.env));
var src = args.get(1).toString(args.env); var src = args.get(1).toString(args.env);
DebugContext.get(environment).onSource(filename, src); DebugHandler.get(environment).onSourceLoad(filename, src);
return Value.UNDEFINED; return Value.UNDEFINED;
})); }));

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