Compare commits
46 Commits
v0.10.4-be
...
master
Author | SHA1 | Date | |
---|---|---|---|
45292990b1 | |||
2dcfff689a | |||
2619e50e9b | |||
4bfda6b0a1 | |||
58d6110e1d | |||
120e59577d | |||
efe123b658 | |||
b190367681 | |||
e601749866 | |||
1670b64aaf | |||
1548938537 | |||
e14d85e7a8 | |||
4352550ae9 | |||
3c4d05abd4 | |||
f16d088646 | |||
8b1c2a5e4e | |||
ee8268b144 | |||
fffeac9bac | |||
166e9c0470 | |||
6125772038 | |||
1e982cd2ef | |||
4389d115b6 | |||
208444381e | |||
eff076f6fe | |||
24a4a01d8e | |||
b9a397a7b9 | |||
40f6cfe616 | |||
f712fb09ae | |||
6355a48c6b | |||
343684f9ce | |||
582753440b | |||
01e86b5e70 | |||
29b0c91c5d | |||
961c8cefcc | |||
3b512b64eb | |||
0118379d4e | |||
1be1cded9f | |||
c0b23d50e5 | |||
cacffd01e8 | |||
a115843351 | |||
3623842827 | |||
24d0cb73b6 | |||
7a13b032f8 | |||
5a154c8a69 | |||
ae77e3b55e | |||
c8a89849ee |
6
.github/workflows/tagged-release.yml
vendored
6
.github/workflows/tagged-release.yml
vendored
@ -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
|
80
README.md
80
README.md
@ -2,22 +2,76 @@
|
|||||||
|
|
||||||
**WARNING: Currently, this code is undocumented. Proceed with caution and a psychiatrist.**
|
**WARNING: Currently, this code is undocumented. Proceed with caution and a psychiatrist.**
|
||||||
|
|
||||||
J2S is an engine, capable of running EcmaScript 5, written entirely in Java. This engine has been developed with the goal of being easy to integrate with your preexisting codebase, **THE GOAL OF THIS ENGINE IS NOT PERFORMANCE**. My crude experiments show that this engine is 50x-100x slower than V8, which, although bad, is acceptable for most simple scripting purposes. Note that although the codebase has a Main class, this isn't meant to be a standalone program, but instead a library for running JavaScript code.
|
J2S is an engine, capable of running EcmaScript 5, written entirely in Java. This engine has been developed with the goal of being easy to integrate with your preexisting codebase, **THE GOAL OF THIS ENGINE IS NOT PERFORMANCE**. My crude experiments show that this engine is 50x-100x slower than V8, which, although bad, is acceptable for most simple scripting purposes. A small REPL (`me.topchetoeu.j2s.repl.SimpleRepl`) library with an included simple debugger (`me.topchetoeu.j2s.repl.debug.SimpleDebugger`). These are more or less reference implementations. In the future, most of the primordials logic of `SimpleRepl` will be moved in the "lib" project, but for now, it will stay there.
|
||||||
|
|
||||||
## Example
|
## How to use?
|
||||||
|
|
||||||
The following is going to execute a simple javascript statement:
|
Since this is mostly targeted for integration into other applications, here, examples for invoking JS code from Java will be shown. In the future, a more comprehensive wiki will be made.
|
||||||
|
|
||||||
|
### Setting up an event loop
|
||||||
|
|
||||||
|
First of all, you will want to create an event loop. While not required, 99% of the times you will want to have one.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
var engine = new Engine();
|
var engine = new Engine();
|
||||||
// Initialize a standard environment, with implementations of most basic standard libraries (Object, Array, Symbol, etc.)
|
var thread = engine.start();
|
||||||
var env = Internals.apply(new Environment());
|
|
||||||
|
|
||||||
// Queue code to load internal libraries and start engine
|
|
||||||
var awaitable = engine.pushMsg(false, env, new Filename("tmp", "eval"), "10 + Math.sqrt(5 / 3)", null);
|
|
||||||
// Run the engine on the same thread, until the event loop runs empty
|
|
||||||
engine.run(true);
|
|
||||||
|
|
||||||
// Get our result
|
|
||||||
System.out.println(awaitable.await());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Hooray! Now you have an event loop. The thread that was automatically created is a daemon thread, so it will harakiri when the rest of the application ends. If you don't want to use the built-in thread, you can instead run it with `engine.run(untilEmpty)`. If you pass true (which you most likely need), the event loop will be run blocking-ly until it is empty. Otherwise, it will be run forever.
|
||||||
|
|
||||||
|
### Creating the execution environment
|
||||||
|
|
||||||
|
This is one of the other crucial parts of J2S's architecture - the environment. It contains the global scope, a reference to the event loop, the global scope, the debugger, source mappings and a lot more. To run JS code, you must create an environment:
|
||||||
|
|
||||||
|
```java
|
||||||
|
var env = Environment.empty();
|
||||||
|
env.add(EventLoop.KEY, engine); // Gives
|
||||||
|
env.add(DebugContext.KEY, new DebugContext()); // For source mappings
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see, the environment is nothing more than a simple map of objects that may be of interest to the JS code. Although you can do much more with the environment, we will leave it at that.
|
||||||
|
|
||||||
|
### Registering the compiler
|
||||||
|
|
||||||
|
Since the compiler is a part of the runtime, you need to register it in the environment. You can use the following boilerplate, although a nicer API will be exposed later on:
|
||||||
|
|
||||||
|
```java
|
||||||
|
env.add(Compiler.KEY, (_env, filename, raw, mapper) -> {
|
||||||
|
try {
|
||||||
|
// Invokes the compiler. Will return a CompilerResult, which, along other things,
|
||||||
|
// gives us all the compiled function bodies (aka function scaffoldings, that can be used to construct a function value)
|
||||||
|
var res = JavaScript.compile(env, filename, raw, true);
|
||||||
|
var body = res.body();
|
||||||
|
|
||||||
|
// We'll register the source and function source mappings for debugging
|
||||||
|
DebugContext.get(env).onSource(filename, raw);
|
||||||
|
for (var el : res.all()) {
|
||||||
|
DebugContext.get(env).onFunctionLoad(el.body(), el.map(mapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we will construct the function
|
||||||
|
// Few things to note: we need to pass the environment, the name of the function (the filename),
|
||||||
|
// and the last thing: the captures. Since we are compiling the main function, we don't have
|
||||||
|
// any captures, so we pass an empty array
|
||||||
|
return new CodeFunction(env, filename.toString(), body, new Value[0][]);
|
||||||
|
}
|
||||||
|
catch (SyntaxException e) {
|
||||||
|
// Convert the exception to an engine exception
|
||||||
|
var res = EngineException.ofSyntax(e.msg);
|
||||||
|
// Add the location of the error to its stack trace
|
||||||
|
res.add(env, e.loc.filename() + "", e.loc);
|
||||||
|
throw res;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Evaluating a piece of code on the event loop
|
||||||
|
|
||||||
|
This is what you really want to do: run code! You can do that in the following way:
|
||||||
|
|
||||||
|
```java
|
||||||
|
var result = engine.pushMsg(false, env, Filename.parse("my-app://test.js"), "return 10 + 5 / 3;", Value.UNDEFINED).get();
|
||||||
|
System.out.println(result.toReadable(env));
|
||||||
|
```
|
||||||
|
|
||||||
|
If all goes well, we will get "11.666..." as a result.
|
||||||
|
@ -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 {
|
||||||
|
@ -3,5 +3,5 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
`kotlin-dsl`
|
`kotlin-dsl`
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,7 @@ java {
|
|||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(17);
|
languageVersion = JavaLanguageVersion.of(17);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withJavadocJar();
|
||||||
|
withSourcesJar();
|
||||||
}
|
}
|
||||||
|
@ -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"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ plugins {
|
|||||||
description = "A collection of utils and structures for the rest of the project";
|
description = "A collection of utils and structures for the rest of the project";
|
||||||
|
|
||||||
tasks.processResources {
|
tasks.processResources {
|
||||||
filesMatching("metadata.json", {
|
filesMatching("metadata", {
|
||||||
expand(
|
expand(
|
||||||
"version" to properties["project_version"],
|
"version" to properties["project_version"],
|
||||||
"name" to properties["project_name"],
|
"name" to properties["project_name"],
|
||||||
|
@ -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;
|
||||||
@ -63,8 +63,11 @@ public class Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> T init(Key<T> key, T val) {
|
public <T> T init(Key<T> key, T val) {
|
||||||
if (!has(key)) this.add(key, val);
|
if (!has(key)) {
|
||||||
return val;
|
this.add(key, val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
else return get(key);
|
||||||
}
|
}
|
||||||
public <T> T initFrom(Key<T> key, Supplier<T> val) {
|
public <T> T initFrom(Key<T> key, Supplier<T> val) {
|
||||||
if (!has(key)) {
|
if (!has(key)) {
|
@ -1,4 +1,4 @@
|
|||||||
package me.topchetoeu.j2s.common.parsing;
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.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();
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
3
common/src/main/java/me/topchetoeu/j2s/common/Key.java
Normal file
3
common/src/main/java/me/topchetoeu/j2s/common/Key.java
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
|
public final class Key<T> { }
|
@ -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);
|
||||||
|
|
||||||
@ -32,9 +30,9 @@ public abstract class Location implements Comparable<Location> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
public final Location nextLine() {
|
public final Location nextLine() {
|
||||||
return changeLine(1);
|
return nextLine(1);
|
||||||
}
|
}
|
||||||
public final Location changeLine(int offset) {
|
public final Location nextLine(int offset) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
return new Location() {
|
return new Location() {
|
||||||
@ -60,7 +58,14 @@ public abstract class Location implements Comparable<Location> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int compareTo(Location other) {
|
@Override public int compareTo(Location other) {
|
||||||
int a = filename().toString().compareTo(other.filename().toString());
|
int a;
|
||||||
|
var filenameA = filename();
|
||||||
|
var filenameB = other.filename();
|
||||||
|
if (filenameB == null && filenameA == null) a = 0;
|
||||||
|
else if (filenameA == null) a = -1;
|
||||||
|
else if (filenameB == null) a = 1;
|
||||||
|
else a = filenameA.toString().compareTo(filenameB.toString());
|
||||||
|
|
||||||
int b = Integer.compare(line(), other.line());
|
int b = Integer.compare(line(), other.line());
|
||||||
int c = Integer.compare(start(), other.start());
|
int c = Integer.compare(start(), other.start());
|
||||||
|
|
||||||
@ -79,21 +84,27 @@ public abstract class Location implements Comparable<Location> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Location of(String raw) {
|
public static Location of(String raw) {
|
||||||
var i0 = raw.lastIndexOf(':');
|
var i1 = raw.lastIndexOf(':');
|
||||||
if (i0 < 0) return Location.of(Filename.parse(raw), -1, -1);
|
if (i1 < 0) return Location.of(Filename.parse(raw), -1, -1);
|
||||||
|
|
||||||
var i1 = raw.lastIndexOf(':', i0);
|
var i0 = raw.substring(0, i1).lastIndexOf(':', i1);
|
||||||
if (i0 < 0) {
|
if (i0 < 0) {
|
||||||
try {
|
try {
|
||||||
return Location.of(Filename.parse(raw.substring(0, i0)), Integer.parseInt(raw.substring(i0 + 1)), -1);
|
return Location.of(null, Integer.parseInt(raw.substring(0, i1)) - 1, Integer.parseInt(raw.substring(i1 + 1)) - 1);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {}
|
||||||
return Location.of(Filename.parse(raw), -1, -1);
|
|
||||||
|
try {
|
||||||
|
return Location.of(Filename.parse(raw.substring(0, i1)), Integer.parseInt(raw.substring(i1 + 1)) - 1, -1);
|
||||||
}
|
}
|
||||||
|
catch (NumberFormatException e) {}
|
||||||
|
|
||||||
|
return Location.of(Filename.parse(raw), -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int start, line;
|
int start, line;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
start = Integer.parseInt(raw.substring(i1 + 1));
|
start = Integer.parseInt(raw.substring(i1 + 1));
|
||||||
}
|
}
|
||||||
@ -105,9 +116,9 @@ public abstract class Location implements Comparable<Location> {
|
|||||||
line = Integer.parseInt(raw.substring(i0 + 1, i1));
|
line = Integer.parseInt(raw.substring(i0 + 1, i1));
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
return Location.of(Filename.parse(raw.substring(i1 + 1)), start, -1);
|
return Location.of(Filename.parse(raw.substring(0, i1)), start - 1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Location.of(Filename.parse(raw.substring(0, i0)), start, line);
|
return Location.of(Filename.parse(raw.substring(0, i0)), line - 1, start - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,30 +1,58 @@
|
|||||||
package me.topchetoeu.j2s.common;
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
import me.topchetoeu.j2s.common.json.JSON;
|
|
||||||
import me.topchetoeu.j2s.common.parsing.Filename;
|
|
||||||
|
|
||||||
public class Metadata {
|
public class Metadata {
|
||||||
private static final String VERSION;
|
private static String VERSION;
|
||||||
private static final String AUTHOR;
|
private static String AUTHOR;
|
||||||
private static final String NAME;
|
private static String NAME;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
var data = JSON.parse(new Filename("internal", "metadata.json"), Reading.resourceToString("metadata.json")).map();
|
var raw = Reading.resourceToString("metadata").split("\n");
|
||||||
VERSION = data.string("version");
|
var line = 0;
|
||||||
AUTHOR = data.string("author");
|
var file = "internal://metadata";
|
||||||
NAME = data.string("name");
|
|
||||||
|
for (var el : raw) {
|
||||||
|
line++;
|
||||||
|
|
||||||
|
el = el.trim();
|
||||||
|
if (el.startsWith("#")) continue;
|
||||||
|
if (el.isEmpty()) continue;
|
||||||
|
|
||||||
|
var i = el.indexOf(":");
|
||||||
|
if (i < 0) throw new RuntimeException(String.format("%s:%s: Expected colon on line", file, line));
|
||||||
|
|
||||||
|
var name = el.substring(0, i).trim();
|
||||||
|
var value = el.substring(i + 1).trim();
|
||||||
|
|
||||||
|
switch (name) {
|
||||||
|
case "version":
|
||||||
|
VERSION = value;
|
||||||
|
break;
|
||||||
|
case "author":
|
||||||
|
AUTHOR = value;
|
||||||
|
break;
|
||||||
|
case "name":
|
||||||
|
NAME = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException(String.format("%s:%s: Unexpected metadata key '%s'", file, line, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VERSION == null) throw new RuntimeException(String.format("%s:%s: No version specified", file, line));
|
||||||
|
if (AUTHOR == null) throw new RuntimeException(String.format("%s:%s: No author specified", file, line));
|
||||||
|
if (NAME == null) throw new RuntimeException(String.format("%s:%s: No name specified", file, line));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String version() {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<>();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package me.topchetoeu.j2s.common.environment;
|
|
||||||
|
|
||||||
public final class Key<T> { }
|
|
3
common/src/main/resources/metadata
Normal file
3
common/src/main/resources/metadata
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version: ${version}
|
||||||
|
name: ${name}
|
||||||
|
author: TopchetoEU
|
@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "${version}",
|
|
||||||
"name": "${name}",
|
|
||||||
"author": "TopchetoEU"
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,69 @@
|
|||||||
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class TestEnvironment {
|
||||||
|
private final Key<String> FOO = new Key<>();
|
||||||
|
private final Key<Void> MARKER = new Key<>();
|
||||||
|
|
||||||
|
@Test public void testShouldCreate() {
|
||||||
|
new Environment();
|
||||||
|
Environment.empty();
|
||||||
|
}
|
||||||
|
@Test public void testShouldNotExist() {
|
||||||
|
var env = new Environment();
|
||||||
|
assertEquals(null, env.get(FOO));
|
||||||
|
assertEquals(false, env.has(FOO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldAdd() {
|
||||||
|
var env = new Environment();
|
||||||
|
env.add(FOO, "test");
|
||||||
|
assertEquals("test", env.get(FOO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldGetFromParent() {
|
||||||
|
var parent = new Environment();
|
||||||
|
parent.add(FOO, "test");
|
||||||
|
var child = parent.child();
|
||||||
|
assertEquals("test", child.get(FOO));
|
||||||
|
assertEquals(true, child.has(FOO));
|
||||||
|
}
|
||||||
|
@Test public void testShouldHideParent() {
|
||||||
|
var parent = new Environment();
|
||||||
|
parent.add(FOO, "test");
|
||||||
|
var child = parent.child();
|
||||||
|
child.remove(FOO);
|
||||||
|
assertEquals(null, child.get(FOO));
|
||||||
|
assertEquals(false, child.has(FOO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldAddMarker() {
|
||||||
|
var env = new Environment();
|
||||||
|
env.add(MARKER);
|
||||||
|
assertEquals(true, env.has(MARKER));
|
||||||
|
assertEquals(false, env.hasNotNull(MARKER));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldInitOnce() {
|
||||||
|
var env = new Environment();
|
||||||
|
assertEquals("a", env.init(FOO, "a"));
|
||||||
|
assertEquals("a", env.init(FOO, "b"));
|
||||||
|
assertEquals("a", env.get(FOO));
|
||||||
|
}
|
||||||
|
@Test public void testShouldInitOnceFrom() {
|
||||||
|
var env = new Environment();
|
||||||
|
assertEquals("a", env.initFrom(FOO, () -> "a"));
|
||||||
|
assertEquals("a", env.initFrom(FOO, () -> "b"));
|
||||||
|
assertEquals("a", env.get(FOO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldWrap() {
|
||||||
|
var env = new Environment();
|
||||||
|
assertEquals(env, Environment.wrap(env));
|
||||||
|
assertInstanceOf(Environment.class, Environment.wrap(null));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TestFilename {
|
||||||
|
@Test public void testShouldParseFilePath() {
|
||||||
|
var filename = Filename.parse("file://hello.world");
|
||||||
|
assertEquals("file", filename.protocol);
|
||||||
|
assertEquals("hello.world", filename.path);
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseNoProtocolFilename() {
|
||||||
|
var filename = Filename.parse("hello.world");
|
||||||
|
assertEquals("file", filename.protocol);
|
||||||
|
assertEquals("hello.world", filename.path);
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseAdditionalSlashFilename() {
|
||||||
|
var filename = Filename.parse("test:///hello.world");
|
||||||
|
assertEquals("test", filename.protocol);
|
||||||
|
assertEquals("/hello.world", filename.path);
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseOneSlashFilename() {
|
||||||
|
var filename = Filename.parse("test:/hello.world");
|
||||||
|
assertEquals("file", filename.protocol);
|
||||||
|
assertEquals("test:/hello.world", filename.path);
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseMatroshkaFilename() {
|
||||||
|
var a = Filename.parse("a://b://hello.world");
|
||||||
|
assertEquals("a", a.protocol);
|
||||||
|
assertEquals("b://hello.world", a.path);
|
||||||
|
|
||||||
|
var b = Filename.parse(a.path);
|
||||||
|
assertEquals("b", b.protocol);
|
||||||
|
assertEquals("hello.world", b.path);
|
||||||
|
}
|
||||||
|
}
|
159
common/src/test/java/me/topchetoeu/j2s/common/TestLocation.java
Normal file
159
common/src/test/java/me/topchetoeu/j2s/common/TestLocation.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package me.topchetoeu.j2s.common;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TestLocation {
|
||||||
|
@Test public void testShouldCreateLocation() {
|
||||||
|
var loc = Location.of(new Filename("file", "test.txt"), 10, 5);
|
||||||
|
assertEquals("test.txt", loc.filename().path);
|
||||||
|
assertEquals(10, loc.line());
|
||||||
|
assertEquals(5, loc.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldGetNextLineLocation() {
|
||||||
|
var loc = Location.of("test.txt:10:5");
|
||||||
|
var next = loc.nextLine();
|
||||||
|
assertEquals(new Filename("file", "test.txt"), next.filename());
|
||||||
|
assertEquals(10, next.line());
|
||||||
|
assertEquals(0, next.start());
|
||||||
|
assertEquals(new Filename("file", "test.txt"), loc.filename());
|
||||||
|
assertEquals(9, loc.line());
|
||||||
|
assertEquals(4, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldGetNextNthLineLocation() {
|
||||||
|
var loc = Location.of(new Filename("file", "test.txt"), 10, 5);
|
||||||
|
var next = loc.nextLine(5);
|
||||||
|
assertEquals(15, next.line());
|
||||||
|
assertEquals(0, next.start());
|
||||||
|
assertEquals(10, loc.line());
|
||||||
|
assertEquals(5, loc.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldGetNextLocation() {
|
||||||
|
var loc = Location.of("test:10:5");
|
||||||
|
var next = loc.add(10);
|
||||||
|
assertEquals(new Filename("file", "test"), next.filename());
|
||||||
|
assertEquals(9, next.line());
|
||||||
|
assertEquals(14, next.start());
|
||||||
|
assertEquals(new Filename("file", "test"), loc.filename());
|
||||||
|
assertEquals(9, loc.line());
|
||||||
|
assertEquals(4, loc.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testShouldParseLocation() {
|
||||||
|
var loc = Location.of("test.txt:10:5");
|
||||||
|
assertEquals(new Filename("file", "test.txt"), loc.filename());
|
||||||
|
assertEquals(9, loc.line());
|
||||||
|
assertEquals(4, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseComplexFilenameLocation() {
|
||||||
|
var loc = Location.of("testificate://test.txt:10:5");
|
||||||
|
assertEquals(new Filename("testificate", "test.txt"), loc.filename());
|
||||||
|
assertEquals(9, loc.line());
|
||||||
|
assertEquals(4, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseNoFilenameLocation() {
|
||||||
|
var loc = Location.of("10:5");
|
||||||
|
assertEquals(null, loc.filename());
|
||||||
|
assertEquals(9, loc.line());
|
||||||
|
assertEquals(4, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseNoStartLocationA() {
|
||||||
|
var loc = Location.of("file://10:5");
|
||||||
|
assertEquals(new Filename("file", "10"), loc.filename());
|
||||||
|
assertEquals(4, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseNoStartLocationB() {
|
||||||
|
var loc = Location.of("file:5");
|
||||||
|
assertEquals(new Filename("file", "file"), loc.filename());
|
||||||
|
assertEquals(4, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseOnlyFilenameLocationA() {
|
||||||
|
var loc = Location.of("http://example.org/test.txt");
|
||||||
|
assertEquals(new Filename("http", "example.org/test.txt"), loc.filename());
|
||||||
|
assertEquals(-1, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseOnlyFilenameLocationB() {
|
||||||
|
var loc = Location.of("test.txt");
|
||||||
|
assertEquals(new Filename("file", "test.txt"), loc.filename());
|
||||||
|
assertEquals(-1, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseOnlyFilenameWithColonLocation() {
|
||||||
|
var loc = Location.of("my-file:bad-file");
|
||||||
|
assertEquals(new Filename("file", "my-file:bad-file"), loc.filename());
|
||||||
|
assertEquals(-1, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
@Test public void testShouldParseOnlyFilenameWithTripleColonLocation() {
|
||||||
|
var loc = Location.of("a:my-file:bad-file");
|
||||||
|
assertEquals(new Filename("file", "a:my-file:bad-file"), loc.filename());
|
||||||
|
assertEquals(-1, loc.line());
|
||||||
|
assertEquals(-1, loc.start());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testCompareEqualLoc() {
|
||||||
|
var locA = Location.of("test:10:5");
|
||||||
|
var locB = Location.of("test:10:5");
|
||||||
|
|
||||||
|
assertEquals(0, locA.compareTo(locB));
|
||||||
|
assertEquals(0, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
@Test public void testCompareNoFileLoc() {
|
||||||
|
var locA = Location.of("10:5");
|
||||||
|
var locB = Location.of("11:5");
|
||||||
|
|
||||||
|
assertEquals(-1, locA.compareTo(locB));
|
||||||
|
assertEquals(1, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
@Test public void testCompareOneNoFileLoc() {
|
||||||
|
var locA = Location.of("10:5");
|
||||||
|
var locB = Location.of("test:10:5");
|
||||||
|
|
||||||
|
assertEquals(-1, locA.compareTo(locB));
|
||||||
|
assertEquals(1, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
@Test public void testCompareDiffFileLoc() {
|
||||||
|
var locA = Location.of("a:10:5");
|
||||||
|
var locB = Location.of("b:10:5");
|
||||||
|
|
||||||
|
assertEquals(-1, locA.compareTo(locB));
|
||||||
|
assertEquals(1, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
@Test public void testCompareDiffLineLoc() {
|
||||||
|
var locA = Location.of("test:10:5");
|
||||||
|
var locB = Location.of("test:11:5");
|
||||||
|
|
||||||
|
assertEquals(-1, locA.compareTo(locB));
|
||||||
|
assertEquals(1, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
@Test public void testCompareDiffStartLoc() {
|
||||||
|
var locA = Location.of("test:10:5");
|
||||||
|
var locB = Location.of("test:10:10");
|
||||||
|
|
||||||
|
assertEquals(-1, locA.compareTo(locB));
|
||||||
|
assertEquals(1, locB.compareTo(locA));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void testToStringAll() {
|
||||||
|
var locA = Location.of("test:10:5");
|
||||||
|
assertEquals("file://test:10:5", locA.toString());
|
||||||
|
}
|
||||||
|
@Test public void testToStringNoFilename() {
|
||||||
|
var locA = Location.of("10:5");
|
||||||
|
assertEquals("10:5", locA.toString());
|
||||||
|
}
|
||||||
|
@Test public void testToStringNoStart() {
|
||||||
|
var locA = Location.of("file:5");
|
||||||
|
assertEquals("file://file:5", locA.toString());
|
||||||
|
}
|
||||||
|
@Test public void testToStringNoLoc() {
|
||||||
|
var locA = Location.of("file");
|
||||||
|
assertEquals("file://file", locA.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,6 @@ plugins {
|
|||||||
|
|
||||||
description = "A compiler of EcmaScript 5 code to J2S bytecode";
|
description = "A compiler of EcmaScript 5 code to J2S bytecode";
|
||||||
|
|
||||||
tasks.processResources {
|
|
||||||
filesMatching("metadata.json", {
|
|
||||||
expand(
|
|
||||||
"version" to properties["project_version"],
|
|
||||||
"name" to properties["project_name"],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
useJUnitPlatform();
|
useJUnitPlatform();
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
@ -2,27 +2,29 @@ package me.topchetoeu.j2s.compilation;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
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;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
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<>();
|
||||||
@ -64,9 +66,31 @@ public final class CompileResult {
|
|||||||
public void setLocation(Location type) {
|
public void setLocation(Location type) {
|
||||||
setLocation(instructions.size() - 1, type);
|
setLocation(instructions.size() - 1, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocationAndDebug(Location loc, BreakpointType type) {
|
public void setLocationAndDebug(Location loc, BreakpointType type) {
|
||||||
setLocationAndDebug(instructions.size() - 1, loc, type);
|
setLocationAndDebug(instructions.size() - 1, loc, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterable<CompileResult> all() {
|
||||||
|
var stack = new Stack<CompileResult>();
|
||||||
|
stack.push(this);
|
||||||
|
|
||||||
|
return () -> new Iterator<CompileResult>() {
|
||||||
|
@Override public CompileResult next() {
|
||||||
|
if (stack.empty()) return null;
|
||||||
|
else {
|
||||||
|
var res = stack.pop();
|
||||||
|
for (var child : res.children) {
|
||||||
|
stack.push(child);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override public boolean hasNext() {
|
||||||
|
return !stack.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public CompileResult addChild(FunctionNode node, CompileResult res) {
|
public CompileResult addChild(FunctionNode node, CompileResult res) {
|
||||||
this.children.add(res);
|
this.children.add(res);
|
||||||
@ -79,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();
|
||||||
|
|
||||||
@ -100,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
|
||||||
);
|
);
|
||||||
@ -128,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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -53,8 +53,8 @@ public abstract class FunctionNode extends Node {
|
|||||||
target.add(scope.define(param.name).index().toSet(false)).setLocation(param.loc());
|
target.add(scope.define(param.name).index().toSet(false)).setLocation(param.loc());
|
||||||
}
|
}
|
||||||
if (hasSelf) {
|
if (hasSelf) {
|
||||||
target.add(Instruction.loadCalled());
|
target.add(Instruction.loadCalled());
|
||||||
target.add(scope.define(selfName).index().toSet(false));
|
target.add(scope.define(selfName).index().toSet(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
body.compile(target, lastReturn, BreakpointType.NONE);
|
body.compile(target, lastReturn, BreakpointType.NONE);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
@ -286,40 +286,40 @@ public final class JavaScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ParseRes<List<VariableNode>> parseParameters(Source src, int i) {
|
public static ParseRes<List<VariableNode>> parseParameters(Source src, int i) {
|
||||||
var n = Parsing.skipEmpty(src, i);
|
var n = Parsing.skipEmpty(src, i);
|
||||||
|
|
||||||
var openParen = Parsing.parseOperator(src, i + n, "(");
|
var openParen = Parsing.parseOperator(src, i + n, "(");
|
||||||
if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list");
|
if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list");
|
||||||
n += openParen.n;
|
n += openParen.n;
|
||||||
|
|
||||||
var params = new ArrayList<VariableNode>();
|
var params = new ArrayList<VariableNode>();
|
||||||
|
|
||||||
var closeParen = Parsing.parseOperator(src, i + n, ")");
|
var closeParen = Parsing.parseOperator(src, i + n, ")");
|
||||||
n += closeParen.n;
|
n += closeParen.n;
|
||||||
|
|
||||||
if (!closeParen.isSuccess()) {
|
if (!closeParen.isSuccess()) {
|
||||||
while (true) {
|
while (true) {
|
||||||
n += Parsing.skipEmpty(src, i + n);
|
n += Parsing.skipEmpty(src, i + n);
|
||||||
|
|
||||||
var param = VariableNode.parse(src, i + n);
|
var param = VariableNode.parse(src, i + n);
|
||||||
if (!param.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a parameter or a closing brace");
|
if (!param.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a parameter or a closing brace");
|
||||||
n += param.n;
|
n += param.n;
|
||||||
n += Parsing.skipEmpty(src, i + n);
|
n += Parsing.skipEmpty(src, i + n);
|
||||||
|
|
||||||
params.add(param.result);
|
params.add(param.result);
|
||||||
|
|
||||||
if (src.is(i + n, ",")) {
|
if (src.is(i + n, ",")) {
|
||||||
n++;
|
n++;
|
||||||
n += Parsing.skipEmpty(src, i + n);
|
n += Parsing.skipEmpty(src, i + n);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.is(i + n, ")")) {
|
if (src.is(i + n, ")")) {
|
||||||
n++;
|
n++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseRes.res(params, n);
|
return ParseRes.res(params, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<>();
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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,11 +57,12 @@ 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);
|
||||||
|
|
||||||
|
target.add(Instruction.discard());
|
||||||
if (pollute) target.add(Instruction.pushUndefined());
|
if (pollute) target.add(Instruction.pushUndefined());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
@ -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 {
|
@ -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;
|
@ -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;
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
@ -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);
|
@ -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;
|
@ -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;
|
||||||
@ -12,6 +14,8 @@ public class Source {
|
|||||||
private int[] lineStarts;
|
private int[] lineStarts;
|
||||||
|
|
||||||
public Location loc(int offset) {
|
public Location loc(int offset) {
|
||||||
|
if (offset < 0) offset = 0;
|
||||||
|
if (offset > src.length()) offset = src.length();
|
||||||
return new SourceLocation(filename, lineStarts, offset);
|
return new SourceLocation(filename, lineStarts, offset);
|
||||||
}
|
}
|
||||||
public boolean is(int i, char c) {
|
public boolean is(int i, char c) {
|
@ -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;
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
9
doc/text/.gitignore
vendored
Normal file
9
doc/text/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
!/img
|
||||||
|
!/src
|
||||||
|
!/.gitignore
|
||||||
|
!/build
|
||||||
|
!/document.md
|
||||||
|
!/README.md
|
||||||
|
!/requirements.md
|
||||||
|
!/template.html
|
1
doc/text/README.md
Normal file
1
doc/text/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This is the main body of my thesis. **BE WARNED!** It is quite lengthy and written in Bulgarian.
|
42
doc/text/build
Executable file
42
doc/text/build
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/luajit -lsrc.build
|
||||||
|
|
||||||
|
local config = require "config";
|
||||||
|
|
||||||
|
function profession(val)
|
||||||
|
if val == "sys" then
|
||||||
|
return {
|
||||||
|
profession = "481020 „Системен програмист“",
|
||||||
|
specialty = "4810201 „Системно програмиране“",
|
||||||
|
};
|
||||||
|
elseif val == "net" then
|
||||||
|
return combine {
|
||||||
|
profession = "523050 „Техник на компютърни системи“",
|
||||||
|
specialty = "5230502 „Компютърни мрежи“",
|
||||||
|
};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
emit {
|
||||||
|
target = "res.html",
|
||||||
|
template {
|
||||||
|
template = "template.html",
|
||||||
|
year = os.date "%Y",
|
||||||
|
prev_year = os.date "%Y" - 1,
|
||||||
|
config,
|
||||||
|
profession(config.profession),
|
||||||
|
|
||||||
|
build {
|
||||||
|
"requirements.md",
|
||||||
|
content = "requirements",
|
||||||
|
},
|
||||||
|
build {
|
||||||
|
"document.md",
|
||||||
|
content = "content",
|
||||||
|
toc = "toc",
|
||||||
|
ctx = {
|
||||||
|
chapter_format = "Глава %s<br/>",
|
||||||
|
chapter_format_plain = "Глава %s: ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
1304
doc/text/document.md
Normal file
1304
doc/text/document.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
doc/text/img/debugging-example.png
Normal file
BIN
doc/text/img/debugging-example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
4
doc/text/img/dependencies.svg
Normal file
4
doc/text/img/dependencies.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 41 KiB |
BIN
doc/text/img/stack-arr.png
Normal file
BIN
doc/text/img/stack-arr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
14
doc/text/requirements.md
Normal file
14
doc/text/requirements.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: Requirements
|
||||||
|
---
|
||||||
|
|
||||||
|
1. Тема: Среда за изпълнение на „EcmaScript 5“ код за виртуалната машина на „Java“
|
||||||
|
2. Изисквания
|
||||||
|
- Покритие на „ECMA-262 5.1 Edition“ стандарта
|
||||||
|
- Задоволително бързодействие
|
||||||
|
- Възможност за лесно вграждане в други софтуерни продукти
|
||||||
|
- Добри тестове, подробна документация и удобен и интуитивен публичен интерфейс за разработчици
|
||||||
|
3. Съдържание
|
||||||
|
1. Теоретична част
|
||||||
|
2. Практическа част
|
||||||
|
3. Приложение
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user