Compare commits

..

50 Commits

Author SHA1 Message Date
45292990b1
some thesis fixes 2025-01-29 14:12:57 +02:00
2dcfff689a
add page numbers to thesis 2025-01-28 14:33:34 +02:00
2619e50e9b
fix typos in thesis 2025-01-28 13:25:09 +02:00
4bfda6b0a1
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 5m38s
2025-01-28 13:11:29 +02:00
58d6110e1d
fix: stack overflow!! 2025-01-28 13:10:58 +02:00
120e59577d
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 5m45s
2025-01-28 12:53:14 +02:00
efe123b658
wrong build files 2025-01-28 12:52:53 +02:00
b190367681
add thesis text 2025-01-26 18:07:13 +02:00
e601749866
refactor: make Value interface (again?) 2025-01-24 23:04:05 +02:00
1670b64aaf
bump
Some checks failed
tagged-release / Tagged Release (push) Failing after 3m54s
2025-01-24 22:48:34 +02:00
1548938537
small fixes
Some checks failed
tagged-release / Tagged Release (push) Has been cancelled
2025-01-24 22:46:51 +02:00
e14d85e7a8
whitespaces 2025-01-24 22:45:14 +02:00
4352550ae9
move debugging to lib 2025-01-24 22:42:33 +02:00
3c4d05abd4
restructuring of stdlibs 2025-01-24 22:37:52 +02:00
f16d088646
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 5m44s
2025-01-24 05:57:33 +02:00
8b1c2a5e4e
separate more stuff into lib project 2025-01-24 05:57:15 +02:00
ee8268b144
fix: for-in not managing stack correctly 2025-01-24 05:47:44 +02:00
fffeac9bac
fix: name was always 'name'
All checks were successful
tagged-release / Tagged Release (push) Successful in 4m14s
2025-01-24 04:18:35 +02:00
166e9c0470
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 3m56s
2025-01-24 03:26:14 +02:00
6125772038
add package uploading 2025-01-24 02:45:26 +02:00
1e982cd2ef
some minor restructuring 2025-01-24 00:22:15 +02:00
4389d115b6
use only babel 2025-01-24 00:22:03 +02:00
208444381e
move FunctionMap logic away from core 2025-01-24 00:21:51 +02:00
eff076f6fe
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 3m56s
2025-01-22 20:34:46 +02:00
24a4a01d8e
fix warnings 2025-01-22 20:34:36 +02:00
b9a397a7b9
specify babel plugins separately 2025-01-22 20:34:31 +02:00
40f6cfe616
fix: make Function.compile do less stuff 2025-01-22 20:34:00 +02:00
f712fb09ae
refactor: merge TYPEOF instruction into OPERATION 2025-01-22 20:32:55 +02:00
6355a48c6b
fix: forEach is cringe 2025-01-22 20:21:32 +02:00
343684f9ce
move more instructions as intrinsics 2025-01-22 03:57:32 +02:00
582753440b
fix: remove unneeded LOAD_REGEX instruction 2025-01-22 01:54:29 +02:00
01e86b5e70 Merge pull request 'Write some tests' (#33) from topchetoeu/tests into master
Reviewed-on: #33
2025-01-15 18:23:24 +00:00
29b0c91c5d
fix: function mappings were registered incorrectly 2025-01-15 20:12:52 +02:00
961c8cefcc
make arguments null prototype, to follow spec closer 2025-01-15 19:54:12 +02:00
3b512b64eb
move buffers out of runtime 2025-01-15 19:52:53 +02:00
0118379d4e
simple func map tests 2025-01-15 19:51:35 +02:00
1be1cded9f
delete placeholder tests 2025-01-15 19:51:09 +02:00
c0b23d50e5
make common project classes hierarchy flat 2025-01-12 04:31:32 +02:00
cacffd01e8
move JSON and parsing logic to compiler project, decouple JSON and parser from engine logic 2025-01-12 04:27:43 +02:00
a115843351
parseRes tests 2025-01-12 03:23:35 +02:00
3623842827
sanitize Source.loc argument 2025-01-12 03:10:44 +02:00
24d0cb73b6
don't use JSON for parsing metadata 2025-01-11 15:21:14 +02:00
7a13b032f8
add environment tests 2025-01-11 14:19:19 +02:00
5a154c8a69
filename tests 2025-01-11 13:43:02 +02:00
ae77e3b55e
location tests 2025-01-11 13:42:53 +02:00
c8a89849ee
clearing up README 2025-01-10 04:53:11 +02:00
d563fc4919
build: split up into multiple projects, use kotlin DLS
All checks were successful
tagged-release / Tagged Release (push) Successful in 5m23s
2025-01-10 04:14:40 +02:00
9668bccef1
fix: circular dependency on metadata when parsing
All checks were successful
tagged-release / Tagged Release (push) Successful in 2m19s
2025-01-10 00:53:29 +02:00
1d50ff14c5
bump
All checks were successful
tagged-release / Tagged Release (push) Successful in 2m34s
2025-01-10 00:35:04 +02:00
a6c458cb23
rename project from jscript to j2s 2025-01-10 00:34:29 +02:00
265 changed files with 8594 additions and 3994 deletions

View File

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

40
.gitignore vendored
View File

@ -1,6 +1,40 @@
/* /*
!/src /buildSrc/*
!/buildSrc
!/buildSrc
!/buildSrc/src
!/buildSrc/build.gradle.kts
/common/*
!/common
!/common/src
!/common/build.gradle.kts
/runtime/*
!/runtime
!/runtime/src
!/runtime/build.gradle.kts
/compilation/*
!/compilation
!/compilation/src
!/compilation/build.gradle.kts
/repl/*
!/repl
!/repl/src
!/repl/build.gradle.kts
/lib/*
!/lib
!/lib/src
!/lib/build.gradle.kts
!/lib/package.json
!/lib/tsconfig.json
!/lib/rollup.config.js
# !/src
!/doc !/doc
!/tests !/tests
!/.github !/.github
@ -10,8 +44,8 @@
!/LICENSE !/LICENSE
!/README.md !/README.md
!/settings.gradle !/settings.gradle.kts
!/build.gradle !/build.gradle.kts
!/gradle.properties !/gradle.properties
!/package.json !/package.json

View File

@ -1,25 +1,77 @@
# JScript # J2S (Java-JavaScript or Java to JavaScript)
**NOTE: This had nothing to do with Microsoft's dialect of EcmaScript**
**WARNING: Currently, this code is undocumented. Proceed with caution and a psychiatrist.** **WARNING: Currently, this code is undocumented. Proceed with caution and a psychiatrist.**
JScript 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.

View File

@ -1,128 +0,0 @@
import java.text.SimpleDateFormat
plugins {
id 'application';
id 'com.github.node-gradle.node' version '5.0.0';
id 'net.nemerosa.versioning' version '2.15.0';
id 'org.ajoberstar.grgit' version '5.0.0-rc.3'; // required by gradle
// TODO: figure out how to integrate proguard
// id "com.github.xaverkapeller.proguard-annotations"
}
base.archivesName = project.project_name;
version = project.project_version;
group = project.project_group;
description = 'ES5-compliant JavaScript interpreter';
node {
version = '20.0.0';
npmVersion = '8.0.0';
download = true;
}
task compileEnv(type: NpmTask) {
dependsOn npmInstall;
inputs.files('rollup.config.js');
inputs.dir('src/lib/libs');
outputs.files("build/js/env.js");
// group = 'build'
args = ['run', 'build-env'];
}
task compileTypescript(type: NpmTask) {
dependsOn npmInstall;
inputs.files('rollup.config.js');
inputs.dir('src/lib/transpiler');
outputs.files("build/js/ts.js");
// nom nom tasty ram
environment.put("NODE_OPTIONS", "--max-old-space-size=4096");
// group = 'build'
args = ['run', 'build-ts'];
}
repositories {
mavenCentral();
}
dependencies {
annotationProcessor 'com.github.bsideup.jabel:jabel-javac-plugin:0.4.2';
compileOnly 'com.github.bsideup.jabel:jabel-javac-plugin:0.4.2';
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2';
testRuntimeOnly 'org.junit.platform:junit-platform-launcher';
}
java {
sourceCompatibility = JavaVersion.VERSION_17;
targetCompatibility = JavaVersion.VERSION_17;
toolchain {
languageVersion = JavaLanguageVersion.of(17);
}
}
configure([tasks.compileJava]) {
options.release = 8;
}
jar {
manifest {
attributes(
'Main-Class': project.main_class,
'Build-Timestamp': new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
'Build-Branch': versioning.info.branch,
'Build-Revision': versioning.info.commit,
'Build-Jdk': "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']})",
'Build-Author': 'TopchetoEU',
);
}
}
application {
mainClass = project.main_class;
applicationDefaultJvmArgs = ['-Xmx2G', '-Xms2G', '-server', '-Dfile.encoding=UTF-8'];
}
distZip {
eachFile { file ->
if (file.path.contains('bin')) {
file.exclude();
}
}
}
distTar {
eachFile { file ->
if (file.path.contains('bin')) {
file.exclude();
}
}
}
processResources {
dependsOn compileEnv;
dependsOn compileTypescript;
from("build/js") {
into "lib";
}
filesMatching "metadata.json", {
expand(
version: project.project_version,
name: project.project_name,
);
}
}
test {
useJUnitPlatform();
}
wrapper {
gradleVersion = '8.10';
}

23
build.gradle.kts Normal file
View File

@ -0,0 +1,23 @@
plugins {
id("base");
}
version = properties["project_version"].toString();
group = properties["project_group"].toString();
description = "ES5-compliant JavaScript interpreter";
tasks.wrapper {
gradleVersion = "8.10";
}
tasks.build {
for (proj in subprojects) {
dependsOn(proj.tasks.named("build"));
doLast {
copy {
from(proj.buildDir.resolve("libs"));
into("$buildDir/libs");
}
}
}
}

View File

@ -0,0 +1,7 @@
repositories {
mavenCentral();
}
plugins {
`kotlin-dsl`
}

View File

@ -0,0 +1,15 @@
plugins {
id("common");
}
java {
sourceCompatibility = JavaVersion.VERSION_17;
targetCompatibility = JavaVersion.VERSION_17;
toolchain {
languageVersion = JavaLanguageVersion.of(17);
}
withJavadocJar();
withSourcesJar();
}

View File

@ -0,0 +1,47 @@
plugins {
id("java");
id("maven-publish");
}
version = rootProject.version;
group = rootProject.group;
base.archivesName = "${properties["project_name"]}-${project.name}";
tasks.named<JavaCompile>("compileJava") {
options.release.set(8);
}
repositories {
mavenCentral();
}
dependencies {
annotationProcessor("com.github.bsideup.jabel:jabel-javac-plugin:0.4.2");
compileOnly("com.github.bsideup.jabel:jabel-javac-plugin:0.4.2");
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2");
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"]);
}
}
}

18
common/build.gradle.kts Normal file
View File

@ -0,0 +1,18 @@
plugins {
id("common-java");
}
description = "A collection of utils and structures for the rest of the project";
tasks.processResources {
filesMatching("metadata", {
expand(
"version" to properties["project_version"],
"name" to properties["project_name"],
);
});
}
tasks.test {
useJUnitPlatform();
}

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.common.environment; package me.topchetoeu.j2s.common;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -63,9 +63,12 @@ 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)) {
this.add(key, val);
return 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)) {
var res = val.get(); var res = val.get();

View File

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

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.common; package me.topchetoeu.j2s.common;
public class FunctionBody { public class FunctionBody {
public final FunctionBody[] children; public final FunctionBody[] children;

View File

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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
package me.topchetoeu.jscript.common.parsing; package me.topchetoeu.j2s.common;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
public abstract class Location implements Comparable<Location> { public abstract class Location implements Comparable<Location> {
public static final Location INTERNAL = Location.of(new Filename("jscript", "native"), -1, -1); public static final Location INTERNAL = Location.of(new Filename(Metadata.name(), "native"), -1, -1);
public abstract int line(); public abstract int line();
public abstract int start(); public abstract int start();
@ -30,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() {
@ -58,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());
@ -77,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) {}
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); 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));
} }
@ -103,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);
} }
} }

View File

@ -0,0 +1,58 @@
package me.topchetoeu.j2s.common;
public class Metadata {
private static String VERSION;
private static String AUTHOR;
private static String NAME;
static {
var raw = Reading.resourceToString("metadata").split("\n");
var line = 0;
var file = "internal://metadata";
for (var el : raw) {
line++;
el = el.trim();
if (el.startsWith("#")) continue;
if (el.isEmpty()) continue;
var i = el.indexOf(":");
if (i < 0) throw new RuntimeException(String.format("%s:%s: Expected colon on line", file, line));
var name = el.substring(0, i).trim();
var value = el.substring(i + 1).trim();
switch (name) {
case "version":
VERSION = value;
break;
case "author":
AUTHOR = value;
break;
case "name":
NAME = 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() {
if (VERSION.equals("${VERSION}")) return "1337-devel";
else return VERSION;
}
public static String author() {
if (AUTHOR.equals("${AUTHOR}")) return "anonymous";
else return AUTHOR;
}
public static String name() {
if (NAME.equals("${NAME}")) return "some-product";
else return NAME;
}
}

View File

@ -0,0 +1,55 @@
package me.topchetoeu.j2s.common;
import java.util.HashMap;
public enum Operation {
TYPEOF(0x10, 1),
INSTANCEOF(0x11, 2),
IN(0x12, 2),
MULTIPLY(0x20, 2),
DIVIDE(0x21, 2),
MODULO(0x22, 2),
ADD(0x23, 2),
SUBTRACT(0x24, 2),
USHIFT_RIGHT(0x30, 2),
SHIFT_RIGHT(0x31, 2),
SHIFT_LEFT(0x32, 2),
GREATER(0x40, 2),
LESS(0x41, 2),
GREATER_EQUALS(0x42, 2),
LESS_EQUALS(0x43, 2),
LOOSE_EQUALS(0x44, 2),
LOOSE_NOT_EQUALS(0x45, 2),
EQUALS(0x46, 2),
NOT_EQUALS(0x47, 2),
AND(0x50, 2),
OR(0x51, 2),
XOR(0x52, 2),
NEG(0x60, 1),
POS(0x61, 1),
NOT(0x62, 1),
INVERSE(0x63, 1);
private static final HashMap<Integer, Operation> operations = new HashMap<>();
static {
for (var val : Operation.values()) operations.put(val.numeric, val);
}
public final int numeric;
public final int operands;
private Operation(int numeric, int n) {
this.numeric = numeric;
this.operands = n;
}
public static Operation fromNumeric(int i) {
return operations.get(i);
}
}

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.common; package me.topchetoeu.j2s.common;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;

View File

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

View File

@ -1,6 +1,4 @@
package me.topchetoeu.jscript.common; package me.topchetoeu.j2s.common;
import me.topchetoeu.jscript.common.parsing.Location;
public class SyntaxException extends RuntimeException { public class SyntaxException extends RuntimeException {
public final Location loc; public final Location loc;

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,13 @@
plugins {
id("common-java");
}
description = "A compiler of EcmaScript 5 code to J2S bytecode";
tasks.test {
useJUnitPlatform();
}
dependencies {
implementation(project(":common"));
}

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.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.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.j2s.common.FunctionMap;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
public class FunctionMap { public final class CompilationFunctionMap implements FunctionMap {
public static class FunctionMapBuilder { public static class FunctionMapBuilder {
private Location first, last;
private final TreeMap<Integer, Location> sourceMap = new TreeMap<>(); private final TreeMap<Integer, Location> sourceMap = new TreeMap<>();
private final HashMap<Location, BreakpointType> breakpoints = new HashMap<>(); private final HashMap<Location, BreakpointType> breakpoints = new HashMap<>();
@ -33,6 +35,9 @@ public class FunctionMap {
} }
public FunctionMapBuilder setLocation(int i, Location loc) { public FunctionMapBuilder setLocation(int i, Location loc) {
if (loc == null || i < 0) return this; if (loc == null || i < 0) return this;
if (first == null || first.compareTo(loc) > 0) first = loc;
if (last == null || last.compareTo(loc) < 0) last = loc;
sourceMap.put(i, loc); sourceMap.put(i, loc);
return this; return this;
} }
@ -43,12 +48,10 @@ public class FunctionMap {
} }
public Location first() { public Location first() {
if (sourceMap.size() == 0) return null; return first;
return sourceMap.firstEntry().getValue();
} }
public Location last() { public Location last() {
if (sourceMap.size() == 0) return null; return last;
return sourceMap.lastEntry().getValue();
} }
public FunctionMapBuilder map(Function<Location, Location> mapper) { public FunctionMapBuilder map(Function<Location, Location> mapper) {
@ -75,17 +78,17 @@ public class FunctionMap {
return this; return this;
} }
public FunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) { public CompilationFunctionMap build(String[] localNames, String[] capturableNames, String[] captureNames) {
return new FunctionMap(sourceMap, breakpoints, localNames, capturableNames, captureNames); return new CompilationFunctionMap(sourceMap, breakpoints, first, last, localNames, capturableNames, captureNames);
} }
public FunctionMap build(Function<Location, Location> mapper) { public CompilationFunctionMap build() {
return new FunctionMap(sourceMap, breakpoints, new String[0], new String[0], new String[0]); return new CompilationFunctionMap(sourceMap, breakpoints, first, last, new String[0], new String[0], new String[0]);
} }
private FunctionMapBuilder() { } private FunctionMapBuilder() { }
} }
public static final FunctionMap EMPTY = new FunctionMap(); public static final CompilationFunctionMap EMPTY = new CompilationFunctionMap();
private final HashMap<Integer, BreakpointType> bps = new HashMap<>(); private final HashMap<Integer, BreakpointType> bps = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpLocs = new HashMap<>(); private final HashMap<Filename, TreeSet<Location>> bpLocs = new HashMap<>();
@ -93,28 +96,29 @@ public class FunctionMap {
private final TreeMap<Integer, Location> pcToLoc = new TreeMap<>(); private final TreeMap<Integer, Location> pcToLoc = new TreeMap<>();
public final String[] localNames, capturableNames, captureNames; public final String[] localNames, capturableNames, captureNames;
public final Location first, last;
public Location toLocation(int pc, boolean approxiamte) { @Override public Location toLocation(int pc, boolean approximate) {
if (pcToLoc.size() == 0 || pc < 0 || pc > pcToLoc.lastKey()) return null; if (pcToLoc.size() == 0 || pc < 0 || pc > pcToLoc.lastKey()) return null;
var res = pcToLoc.get(pc); var res = pcToLoc.get(pc);
if (!approxiamte || res != null) return res; if (!approximate || res != null) return res;
var entry = pcToLoc.headMap(pc, true).lastEntry(); var entry = pcToLoc.headMap(pc, true).lastEntry();
if (entry == null) return null; if (entry == null) return null;
else return entry.getValue(); else return entry.getValue();
} }
public Location toLocation(int pc) { @Override public Location toLocation(int pc) {
return toLocation(pc, false); return toLocation(pc, false);
} }
public BreakpointType getBreakpoint(int pc) { @Override public BreakpointType getBreakpoint(int pc) {
return bps.getOrDefault(pc, BreakpointType.NONE); return bps.getOrDefault(pc, BreakpointType.NONE);
} }
public Location correctBreakpoint(Location loc) { @Override public Location correctBreakpoint(Location loc) {
var set = bpLocs.get(loc.filename()); var set = bpLocs.get(loc.filename());
if (set == null) return null; if (set == null) return null;
else return set.ceiling(loc); else return set.ceiling(loc);
} }
public List<Location> correctBreakpoint(Pattern filename, int line, int column) { @Override public List<Location> correctBreakpoint(Pattern filename, int line, int column) {
var candidates = new HashMap<Filename, TreeSet<Location>>(); var candidates = new HashMap<Filename, TreeSet<Location>>();
for (var name : bpLocs.keySet()) { for (var name : bpLocs.keySet()) {
@ -132,7 +136,7 @@ public class FunctionMap {
return res; return res;
} }
public List<Location> breakpoints(Location start, Location end) { @Override public List<Location> breakpoints(Location start, Location end) {
if (!Objects.equals(start.filename(), end.filename())) return Arrays.asList(); if (!Objects.equals(start.filename(), end.filename())) return Arrays.asList();
NavigableSet<Location> set = bpLocs.get(start.filename()); NavigableSet<Location> set = bpLocs.get(start.filename());
if (set == null) return Arrays.asList(); if (set == null) return Arrays.asList();
@ -152,8 +156,25 @@ public class FunctionMap {
return pcToLoc.lastEntry().getValue(); return pcToLoc.lastEntry().getValue();
} }
public FunctionMap clone() { @Override public Location first() {
var res = new FunctionMap(new HashMap<>(), new HashMap<>(), localNames, capturableNames, captureNames); return first;
}
@Override public Location last() {
return last;
}
@Override public String[] capturableNames() {
return capturableNames;
}
@Override public String[] captureNames() {
return captureNames;
}
@Override public String[] localNames() {
return localNames;
}
public CompilationFunctionMap clone() {
var res = new CompilationFunctionMap(new HashMap<>(), new HashMap<>(), first, last, localNames, capturableNames, captureNames);
res.pcToLoc.putAll(this.pcToLoc); res.pcToLoc.putAll(this.pcToLoc);
res.bps.putAll(bps); res.bps.putAll(bps);
res.bpLocs.putAll(bpLocs); res.bpLocs.putAll(bpLocs);
@ -161,7 +182,7 @@ public class FunctionMap {
return res; return res;
} }
public FunctionMap(Map<Integer, Location> map, Map<Location, BreakpointType> breakpoints, String[] localNames, String[] capturableNames, String[] captureNames) { public CompilationFunctionMap(Map<Integer, Location> map, Map<Location, BreakpointType> breakpoints, Location first, Location last, String[] localNames, String[] capturableNames, String[] captureNames) {
var locToPc = new HashMap<Location, Integer>(); var locToPc = new HashMap<Location, Integer>();
for (var el : map.entrySet()) { for (var el : map.entrySet()) {
@ -180,11 +201,16 @@ public class FunctionMap {
this.localNames = localNames; this.localNames = localNames;
this.captureNames = captureNames; this.captureNames = captureNames;
this.capturableNames = capturableNames; this.capturableNames = capturableNames;
this.first = first;
this.last = last;
} }
private FunctionMap() { private CompilationFunctionMap() {
localNames = new String[0]; localNames = new String[0];
captureNames = new String[0]; captureNames = new String[0];
capturableNames = new String[0]; capturableNames = new String[0];
first = null;
last = null;
} }
public static FunctionMapBuilder builder() { public static FunctionMapBuilder builder() {

View File

@ -1,27 +1,30 @@
package me.topchetoeu.jscript.compilation; 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.Instruction;
import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.j2s.compilation.CompilationFunctionMap.FunctionMapBuilder;
import me.topchetoeu.j2s.compilation.control.TryNode;
import me.topchetoeu.j2s.compilation.scope.FunctionScope;
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;
import me.topchetoeu.jscript.common.FunctionBody;
import me.topchetoeu.jscript.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.common.environment.Key;
import me.topchetoeu.jscript.common.mapping.FunctionMap;
import me.topchetoeu.jscript.common.mapping.FunctionMap.FunctionMapBuilder;
import me.topchetoeu.jscript.common.parsing.Location;
import me.topchetoeu.jscript.compilation.control.TryNode;
import me.topchetoeu.jscript.compilation.scope.FunctionScope;
import me.topchetoeu.jscript.compilation.scope.Variable;
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<>();
@ -63,10 +66,32 @@ 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);
this.childrenMap.put(node, res); this.childrenMap.put(node, res);
@ -78,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();
@ -99,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
); );
@ -127,7 +154,7 @@ public final class CompileResult {
this.scope = scope; this.scope = scope;
this.instructions = new ArrayList<>(); this.instructions = new ArrayList<>();
this.children = new LinkedList<>(); this.children = new LinkedList<>();
this.map = FunctionMap.builder(); this.map = CompilationFunctionMap.builder();
this.env = env; this.env = env;
this.length = length; this.length = length;
} }

View File

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

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;

View File

@ -1,16 +1,16 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.List; import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.scope.FunctionScope; import me.topchetoeu.j2s.compilation.scope.FunctionScope;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
public abstract class FunctionNode extends Node { public abstract class FunctionNode extends Node {
public final CompoundNode body; public final CompoundNode body;

View File

@ -1,12 +1,12 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.List; import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.compilation.scope.Variable; import me.topchetoeu.j2s.compilation.scope.Variable;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
public class FunctionStatementNode extends FunctionNode { public class FunctionStatementNode extends FunctionNode {
public final String name; public final String name;

View File

@ -1,11 +1,11 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.List; import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
public class FunctionValueNode extends FunctionNode { public class FunctionValueNode extends FunctionNode {
public final String name; public final String name;

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -6,45 +6,45 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import me.topchetoeu.jscript.common.SyntaxException; import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.control.BreakNode;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.control.ContinueNode;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.control.DebugNode;
import me.topchetoeu.jscript.compilation.control.BreakNode; import me.topchetoeu.j2s.compilation.control.DeleteNode;
import me.topchetoeu.jscript.compilation.control.ContinueNode; import me.topchetoeu.j2s.compilation.control.DoWhileNode;
import me.topchetoeu.jscript.compilation.control.DebugNode; import me.topchetoeu.j2s.compilation.control.ForInNode;
import me.topchetoeu.jscript.compilation.control.DeleteNode; import me.topchetoeu.j2s.compilation.control.ForNode;
import me.topchetoeu.jscript.compilation.control.DoWhileNode; import me.topchetoeu.j2s.compilation.control.IfNode;
import me.topchetoeu.jscript.compilation.control.ForInNode; import me.topchetoeu.j2s.compilation.control.ReturnNode;
import me.topchetoeu.jscript.compilation.control.ForNode; import me.topchetoeu.j2s.compilation.control.SwitchNode;
import me.topchetoeu.jscript.compilation.control.IfNode; import me.topchetoeu.j2s.compilation.control.ThrowNode;
import me.topchetoeu.jscript.compilation.control.ReturnNode; import me.topchetoeu.j2s.compilation.control.TryNode;
import me.topchetoeu.jscript.compilation.control.SwitchNode; import me.topchetoeu.j2s.compilation.control.WhileNode;
import me.topchetoeu.jscript.compilation.control.ThrowNode; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.control.TryNode; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.control.WhileNode; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.scope.FunctionScope; import me.topchetoeu.j2s.compilation.scope.FunctionScope;
import me.topchetoeu.jscript.compilation.values.ArgumentsNode; import me.topchetoeu.j2s.compilation.values.ArgumentsNode;
import me.topchetoeu.jscript.compilation.values.ArrayNode; import me.topchetoeu.j2s.compilation.values.ArrayNode;
import me.topchetoeu.jscript.compilation.values.GlobalThisNode; import me.topchetoeu.j2s.compilation.values.GlobalThisNode;
import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.j2s.compilation.values.ObjectNode;
import me.topchetoeu.jscript.compilation.values.RegexNode; import me.topchetoeu.j2s.compilation.values.RegexNode;
import me.topchetoeu.jscript.compilation.values.ThisNode; import me.topchetoeu.j2s.compilation.values.ThisNode;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.values.constants.BoolNode; import me.topchetoeu.j2s.compilation.values.constants.BoolNode;
import me.topchetoeu.jscript.compilation.values.constants.NullNode; import me.topchetoeu.j2s.compilation.values.constants.NullNode;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;
import me.topchetoeu.jscript.compilation.values.operations.CallNode; import me.topchetoeu.j2s.compilation.values.operations.CallNode;
import me.topchetoeu.jscript.compilation.values.operations.ChangeNode; import me.topchetoeu.j2s.compilation.values.operations.ChangeNode;
import me.topchetoeu.jscript.compilation.values.operations.DiscardNode; import me.topchetoeu.j2s.compilation.values.operations.DiscardNode;
import me.topchetoeu.jscript.compilation.values.operations.IndexNode; import me.topchetoeu.j2s.compilation.values.operations.IndexNode;
import me.topchetoeu.jscript.compilation.values.operations.OperationNode; import me.topchetoeu.j2s.compilation.values.operations.OperationNode;
import me.topchetoeu.jscript.compilation.values.operations.PostfixNode; import me.topchetoeu.j2s.compilation.values.operations.PostfixNode;
import me.topchetoeu.jscript.compilation.values.operations.TypeofNode; import me.topchetoeu.j2s.compilation.values.operations.TypeofNode;
public final class JavaScript { public final class JavaScript {
public static enum DeclarationType { public static enum DeclarationType {

View File

@ -1,15 +1,15 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; 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.jscript.common.Instruction; import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.jscript.common.SyntaxException; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.j2s.common.Key;
import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.SyntaxException;
public class LabelContext { public class LabelContext {
public static final Key<LabelContext> BREAK_CTX = new Key<>(); public static final Key<LabelContext> BREAK_CTX = new Key<>();

View File

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

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation; package me.topchetoeu.j2s.compilation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,16 +1,16 @@
package me.topchetoeu.jscript.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
import me.topchetoeu.jscript.compilation.values.constants.BoolNode; import me.topchetoeu.j2s.compilation.values.constants.BoolNode;
import me.topchetoeu.jscript.compilation.values.operations.IndexNode; import me.topchetoeu.j2s.compilation.values.operations.IndexNode;
public class DeleteNode extends Node { public class DeleteNode extends Node {
public final Node key; public final Node key;

View File

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

View File

@ -1,17 +1,17 @@
package me.topchetoeu.jscript.compilation.control; package me.topchetoeu.j2s.compilation.control;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.DeferredIntSupplier;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.LabelContext;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.LabelContext; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.DeferredIntSupplier; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
public class ForInNode extends Node { public class ForInNode extends Node {
public final boolean isDecl; public final boolean isDecl;
@ -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());
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,15 +1,16 @@
package me.topchetoeu.jscript.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.jscript.common.SyntaxException; import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Metadata;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.common.StringifyUtils;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.j2s.compilation.parsing.Source;
public class JSON { public class JSON {
public static ParseRes<JSONElement> parseString(Source src, int i) { public static ParseRes<JSONElement> parseString(Source src, int i) {
@ -100,7 +101,7 @@ public class JSON {
return ParseRes.res(JSONElement.list(values), n); return ParseRes.res(JSONElement.list(values), n);
} }
public static JSONElement parse(Filename filename, String raw) { public static JSONElement parse(Filename filename, String raw) {
if (filename == null) filename = new Filename("jscript", "json"); if (filename == null) filename = new Filename(Metadata.name(), "json");
var res = parseValue(new Source(null, filename, raw), 0); var res = parseValue(new Source(null, filename, raw), 0);
if (res.isFailed()) throw new SyntaxException(Location.of(filename, 0, 0), "Invalid JSON given"); if (res.isFailed()) throw new SyntaxException(Location.of(filename, 0, 0), "Invalid JSON given");
@ -109,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++) {
@ -155,7 +129,7 @@ public class JSON {
for (int i = 0; i < entries.size(); i++) { for (int i = 0; i < entries.size(); i++) {
if (i != 0) res.append(","); if (i != 0) res.append(",");
res.append(stringify(JSONElement.string(entries.get(i).getKey()))); res.append(StringifyUtils.quoteString(entries.get(i).getKey()));
res.append(":"); res.append(":");
res.append(stringify(entries.get(i).getValue())); res.append(stringify(entries.get(i).getValue()));
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,11 @@
package me.topchetoeu.j2s.compilation.members;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.compilation.CompileResult;
public interface Member {
Location loc();
void compileFunctions(CompileResult target);
void compile(CompileResult target, boolean pollute);
}

View File

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

View File

@ -1,4 +1,6 @@
package me.topchetoeu.jscript.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,13 +35,14 @@ 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")
@ -63,7 +66,6 @@ public class ParseRes<T> {
return new ParseRes<>(State.SUCCESS, null, null, val, i); return new ParseRes<>(State.SUCCESS, null, null, val, i);
} }
@SafeVarargs
@SuppressWarnings("all") @SuppressWarnings("all")
public static <T> ParseRes<T> first(Source src, int i, Parser ...parsers) { public static <T> ParseRes<T> first(Source src, int i, Parser ...parsers) {
int n = Parsing.skipEmpty(src, i); int n = Parsing.skipEmpty(src, i);

View File

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

View File

@ -1,7 +1,4 @@
package me.topchetoeu.jscript.common.parsing; package me.topchetoeu.j2s.compilation.parsing;
import me.topchetoeu.jscript.common.SyntaxException;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode;
public class Parsing { public class Parsing {
public static boolean isDigit(Character c) { public static boolean isDigit(Character c) {
@ -19,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++;
} }
@ -89,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;
@ -104,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;
@ -346,8 +342,8 @@ public class Parsing {
if (negative) return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus"); if (negative) return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus");
return ParseRes.failed(); return ParseRes.failed();
} }
else if (negative) return ParseRes.res(-(whole + fract) * NumberNode.power(10, exponent), n); else if (negative) return ParseRes.res(-(whole + fract) * power(10, exponent), n);
else return ParseRes.res((whole + fract) * NumberNode.power(10, exponent), n); else return ParseRes.res((whole + fract) * power(10, exponent), n);
} }
public static ParseRes<Double> parseFloat(Source src, int i, boolean withMinus) { public static ParseRes<Double> parseFloat(Source src, int i, boolean withMinus) {
var n = skipEmpty(src, i); var n = skipEmpty(src, i);
@ -406,9 +402,10 @@ public class Parsing {
if (negative) return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus"); if (negative) return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus");
return ParseRes.failed(); return ParseRes.failed();
} }
else if (negative) return ParseRes.res(-(whole + fract) * NumberNode.power(10, exponent), n); else if (negative) return ParseRes.res(-(whole + fract) * power(10, exponent), n);
else return ParseRes.res((whole + fract) * NumberNode.power(10, exponent), n); else return ParseRes.res((whole + fract) * power(10, exponent), n);
} }
public static ParseRes<Double> parseInt(Source src, int i, String alphabet, boolean withMinus) { public static ParseRes<Double> parseInt(Source src, int i, String alphabet, boolean withMinus) {
var n = skipEmpty(src, i); var n = skipEmpty(src, i);
@ -425,16 +422,20 @@ public class Parsing {
n += 2; n += 2;
var res = parseHex(src, i); var res = parseHex(src, i);
if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Incomplete hexadecimal literal"); if (!res.isSuccess())
return res.chainError(src.loc(i + n), "Incomplete hexadecimal literal");
n += res.n; n += res.n;
if (negative) return ParseRes.res(-res.result, n); if (negative)
else return ParseRes.res(res.result, n); return ParseRes.res(-res.result, n);
else
return ParseRes.res(res.result, n);
} }
while (true) { while (true) {
var digit = alphabet.indexOf(Character.toLowerCase(src.at(i + n, '\0'))); var digit = alphabet.indexOf(Character.toLowerCase(src.at(i + n, '\0')));
if (digit < 0) break; if (digit < 0)
break;
parsedAny = true; parsedAny = true;
result *= alphabet.length(); result *= alphabet.length();
@ -443,10 +444,21 @@ public class Parsing {
} }
if (!parsedAny) { if (!parsedAny) {
if (negative) return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus"); if (negative)
return ParseRes.error(src.loc(i + n), "Expected number immediatly after minus");
return ParseRes.failed(); return ParseRes.failed();
} else if (negative)
return ParseRes.res(-result, n);
else
return ParseRes.res(result, n);
} }
else if (negative) return ParseRes.res(-result, n);
else return ParseRes.res(result, n); 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);
} }
} }

View File

@ -1,8 +1,10 @@
package me.topchetoeu.jscript.common.parsing; package me.topchetoeu.j2s.compilation.parsing;
import java.util.function.Predicate; import java.util.function.Predicate;
import me.topchetoeu.jscript.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) {

View File

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

View File

@ -1,7 +1,7 @@
package me.topchetoeu.jscript.compilation.patterns; package me.topchetoeu.j2s.compilation.patterns;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
/** /**
* Represents all nodes that can be assign targets * Represents all nodes that can be assign targets

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation.patterns; package me.topchetoeu.j2s.compilation.patterns;
/** /**
* Represents all nodes that can be converted to assign targets * Represents all nodes that can be converted to assign targets

View File

@ -0,0 +1,7 @@
package me.topchetoeu.j2s.compilation.patterns;
import me.topchetoeu.j2s.compilation.CompileResult;
public interface ChangeTarget extends AssignTarget {
void beforeChange(CompileResult target);
}

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation.scope; package me.topchetoeu.j2s.compilation.scope;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -32,7 +32,7 @@ public final class FunctionScope {
} }
/** /**
* @returns If a variable with the same name exists, the old variable. Otherwise, the given variable * @return If a variable with the same name exists, the old variable. Otherwise, the given variable
*/ */
public Variable define(Variable var) { public Variable define(Variable var) {
if (passthrough) return null; if (passthrough) return null;
@ -48,7 +48,7 @@ public final class FunctionScope {
} }
/** /**
* @returns A variable with the given name, or null if a global variable * @return A variable with the given name, or null if a global variable
*/ */
public Variable define(String name) { public Variable define(String name) {
return define(new Variable(name, false)); return define(new Variable(name, false));

View File

@ -1,4 +1,4 @@
package me.topchetoeu.jscript.compilation.scope; package me.topchetoeu.j2s.compilation.scope;
import java.util.function.Supplier; import java.util.function.Supplier;

View File

@ -1,6 +1,6 @@
package me.topchetoeu.jscript.compilation.scope; package me.topchetoeu.j2s.compilation.scope;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
public final class VariableIndex { public final class VariableIndex {
public static enum IndexType { public static enum IndexType {
@ -39,9 +39,9 @@ public final class VariableIndex {
} }
public final Instruction toSet(boolean keep) { public final Instruction toSet(boolean keep) {
switch (type) { switch (type) {
case CAPTURES: return Instruction.storeVar(~index, keep, false); case CAPTURES: return Instruction.storeVar(~index, keep);
case CAPTURABLES: return Instruction.storeVar(index, keep, false); case CAPTURABLES: return Instruction.storeVar(index, keep);
case LOCALS: return Instruction.storeVar(index, keep, false); case LOCALS: return Instruction.storeVar(index, keep);
default: throw new UnsupportedOperationException("Unknown index type " + type); default: throw new UnsupportedOperationException("Unknown index type " + type);
} }
} }

View File

@ -1,11 +1,11 @@
package me.topchetoeu.jscript.compilation.scope; package me.topchetoeu.j2s.compilation.scope;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.function.IntSupplier; import java.util.function.IntSupplier;
import java.util.function.Supplier; import java.util.function.Supplier;
import me.topchetoeu.jscript.compilation.scope.VariableIndex.IndexType; import me.topchetoeu.j2s.compilation.scope.VariableIndex.IndexType;
public final class VariableList implements Iterable<Variable> { public final class VariableList implements Iterable<Variable> {
private final class VariableNode implements Supplier<VariableIndex> { private final class VariableNode implements Supplier<VariableIndex> {
@ -175,7 +175,7 @@ public final class VariableList implements Iterable<Variable> {
this.offset = () -> offset; this.offset = () -> offset;
} }
/** /**
* @param offset Will offset the indices by the size of the given list * @param prev Will offset the indices by the size of the given list
*/ */
public VariableList(IndexType type, VariableList prev) { public VariableList(IndexType type, VariableList prev) {
this.indexType = type; this.indexType = type;

View File

@ -1,9 +1,9 @@
package me.topchetoeu.jscript.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
public class ArgumentsNode extends Node { public class ArgumentsNode extends Node {

View File

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

View File

@ -1,9 +1,9 @@
package me.topchetoeu.jscript.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
public class GlobalThisNode extends Node { public class GlobalThisNode extends Node {

View File

@ -1,21 +1,21 @@
package me.topchetoeu.jscript.compilation.values; package me.topchetoeu.j2s.compilation.values;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.members.FieldMemberNode;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.members.Member;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.members.PropertyMemberNode;
import me.topchetoeu.jscript.compilation.members.FieldMemberNode; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.members.Member; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.members.PropertyMemberNode; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;
public class ObjectNode extends Node { public class ObjectNode extends Node {
public final List<Member> members; public final List<Member> members;

View File

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

View File

@ -1,9 +1,9 @@
package me.topchetoeu.jscript.compilation.values; package me.topchetoeu.j2s.compilation.values;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
public class ThisNode extends Node { public class ThisNode extends Node {

View File

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

View File

@ -1,9 +1,9 @@
package me.topchetoeu.jscript.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
public class BoolNode extends Node { public class BoolNode extends Node {
public final boolean value; public final boolean value;

View File

@ -1,9 +1,9 @@
package me.topchetoeu.jscript.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
public class NullNode extends Node { public class NullNode extends Node {
@Override public void compileFunctions(CompileResult target) { @Override public void compileFunctions(CompileResult target) {

View File

@ -1,12 +1,12 @@
package me.topchetoeu.jscript.compilation.values.constants; package me.topchetoeu.j2s.compilation.values.constants;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; 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;
@ -23,15 +23,6 @@ public class NumberNode extends Node {
this.value = value; this.value = value;
} }
public 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 ParseRes<NumberNode> parse(Source src, int i) { public static ParseRes<NumberNode> parse(Source src, int i) {
var n = Parsing.skipEmpty(src, i); var n = Parsing.skipEmpty(src, i);
var loc = src.loc(i + n); var loc = src.loc(i + n);

View File

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

View File

@ -1,12 +1,12 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.SyntaxException; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.SyntaxException;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.patterns.AssignTarget; import me.topchetoeu.j2s.compilation.patterns.AssignTarget;
public class AssignNode extends Node implements AssignTarget { public class AssignNode extends Node implements AssignTarget {
public final AssignTarget assignable; public final AssignTarget assignable;

View File

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

View File

@ -1,16 +1,16 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget; import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
public class ChangeNode extends Node { public class ChangeNode extends Node {
public final ChangeTarget changable; public final ChangeTarget changable;

View File

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

View File

@ -1,17 +1,17 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Instruction.BreakpointType;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget; import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
import me.topchetoeu.jscript.compilation.values.constants.StringNode; import me.topchetoeu.j2s.compilation.values.constants.StringNode;
public class IndexNode extends Node implements ChangeTarget { public class IndexNode extends Node implements ChangeTarget {
public final Node object; public final Node object;

View File

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

View File

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

View File

@ -1,21 +1,21 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.JavaScript;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.patterns.AssignTargetLike; import me.topchetoeu.j2s.compilation.patterns.AssignTargetLike;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget; import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
public class OperationNode extends Node { public class OperationNode extends Node {
private static interface OperatorFactory { private static interface OperatorFactory {

View File

@ -1,15 +1,15 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.j2s.compilation.parsing.ParseRes;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.parsing.Parsing;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.parsing.Source;
import me.topchetoeu.jscript.compilation.patterns.ChangeTarget; import me.topchetoeu.j2s.compilation.patterns.ChangeTarget;
import me.topchetoeu.jscript.compilation.values.constants.NumberNode; import me.topchetoeu.j2s.compilation.values.constants.NumberNode;
public class PostfixNode extends ChangeNode { public class PostfixNode extends ChangeNode {
@Override public void compileFunctions(CompileResult target) { @Override public void compileFunctions(CompileResult target) {

View File

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

View File

@ -1,12 +1,12 @@
package me.topchetoeu.jscript.compilation.values.operations; package me.topchetoeu.j2s.compilation.values.operations;
import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.j2s.common.Operation;
import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.j2s.compilation.CompileResult;
import me.topchetoeu.jscript.compilation.FunctionNode; import me.topchetoeu.j2s.compilation.FunctionNode;
import me.topchetoeu.jscript.compilation.Node; import me.topchetoeu.j2s.compilation.Node;
import me.topchetoeu.jscript.compilation.values.VariableNode; import me.topchetoeu.j2s.compilation.values.VariableNode;
public class VariableAssignNode extends Node { public class VariableAssignNode extends Node {
public final String name; public final String name;

View File

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

View File

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

View File

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

View File

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

9
doc/text/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/*
!/img
!/src
!/.gitignore
!/build
!/document.md
!/README.md
!/requirements.md
!/template.html

1
doc/text/README.md Normal file
View 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
View 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: ",
},
},
},
}

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