diff --git a/jdk.js b/jdk.js index 41b2988..e98ffa3 100755 --- a/jdk.js +++ b/jdk.js @@ -182,28 +182,46 @@ let className = file.slice(classLine + 13, file.indexOf(' {', classLine + 13)); // workaround hack for converting triple quotes to a normal string - file = file.replaceAll(/"""([^"]*)"""/g, (match, str) => { - str = str.replaceAll(/(.*)(\n|$)/g, '"$1\\n"+').slice(0, -1); - return str; + file = file.replace(/"""([^"]*)"""/gm, (match, p1) => { + return '(' + p1.replace(/( |\t){0,3}(.*)(\n|$)/gm, '"$2\\n"+').slice(0, -1) + ')'; }); // hacky support for Array literals - file = file.replaceAll(/=\s*new \w*\[\]\s*\{/g, '= {'); + file = file.replace(/new\s*\w*\s*\[\s*\]\s*\{(.*)\}/gm, 'new Array($1)'); + + file = file.replace(/new\s*\w*(\s*\[\s*\])*\s*\{(.*)\}/gm, (match, p1, p2) => { + return 'new Array(' + p2.replace(/\{([^\}]*)\}/gm, 'new Array($1)') + ')'; + }); // workaround hack for converting lambda expressions to Runnables let lambdaRegex = /\(\)\s*\->\s*\{(([^\{\}]*\{[^\}]*\})*[^\}]*)\}/g; - file = file.replaceAll(lambdaRegex, (match, in0) => { + + // can't even do this... bruh + // file = file.replace(lambdaRegex, (match, in0) => { + // // log(in0); + // if (lambdaRegex.test(in0)) { + // in0 = in0.replace(lambdaRegex, (match, in1) => { + // return 'new Runnable() {\\n@Override\\npublic void run() {' + in1 + '}\\n}'; + // }); + // } + // return 'new Runnable() {\\n@Override\\npublic void run() {' + in0 + '}\\n}'; + // }); + + // TODO fix this by adding real support for lambda + file = file.replace(lambdaRegex, (match, in0) => { // log(in0); if (lambdaRegex.test(in0)) { - in0 = in0.replaceAll(lambdaRegex, (match, in1) => { - return 'new Runnable() {\n@Override\npublic void run() {' + in1 + '}}'; + in0 = in0.replace(lambdaRegex, (match, in1) => { + in1.replaceAll('\n', '\\n'); + return 'new Runnable("' + in1 + '")'; }); } - return 'new Runnable() {\n@Override\npublic void run() {' + in0 + '}}'; + in0 = in0.replaceAll('\n', '\\n'); + return 'new Runnable("' + in0 + '")'; }); // convert string .length() method - file = file.replaceAll(/\.length\(\)/g, '.length'); + file = file.replace(/\.length\(\)/gm, '.length'); // cast to int, truncates the number (just removes decimal value) file = file.replace(/\(int\)\s*/gm, 'Math.floor'); @@ -213,7 +231,12 @@ // log(trans); - trans = trans.replace(/(\([^\)]*\) =>)/gm, 'async $1'); + // TODO fix this by adding real support for lambda + trans = trans.replace(/new\s*Runnable\('(.*)'\)/, (match, p1) => { + return '() => {' + p1.replaceAll('\\n', '\n') + '}'; + }); + + trans = trans.replace(/(\([^\(\)]*\) =>)/gm, 'async $1'); trans = trans.replace(/([\w_\$]+\.next(Int|Float|Double|Line|Short|Long)*\(\))/gm, 'await $1'); let prefix = `((jdk.imports['games_java.${className}'] = {}).load = async () => {\n\n`; @@ -233,7 +256,7 @@ } prefix += '\n'; - let suffix = `\njdk.main = ${className}.main;\njdk.launch();\n})();`; + let suffix = `\nwindow.${className} = ${className};\njdk.main = ${className}.main;\njdk.launch();\n})();`; trans = prefix + trans + suffix; @@ -19184,8 +19207,12 @@ case 'ArrayInitializer': return `[${expr.expressions.map(parseExpr)}]`; case 'ArrayCreation': - return `new Array()`; // TODOQ multiple dimensions? + return `new Array()`; case 'ArrayAccess': + // TODO support for three dimensional arrays + if (expr.array.array) { + return `${expr.array.array.identifier}[${parseExpr(expr.array.index)}][${parseExpr(expr.index)}]`; + } return `${expr.array.identifier}[${parseExpr(expr.index)}]`; case 'ParenthesizedExpression': return `(${parseExpr(expr.expression)})`; @@ -19352,7 +19379,14 @@ for (const var_ of vars) { if (var_.value === undefined) var_.value = literalInitializers[var_.type] || 'null'; if (var_.static) staticVars.push(`${className}.${var_.name}=${var_.value};`); - else initVars.push(`this.${var_.name}=${var_.value};`); + else { + if (typeof var_.value == 'string') { + for (const vv of vars) { + var_.value = var_.value.replaceAll(vv.name, 'this.' + vv.name); + } + } + initVars.push(`this.${var_.name}=${var_.value};`); + } } let addedConstructor = false; @@ -19365,7 +19399,10 @@ isConstructor && addInitVars && initVars.length ? initVars.join('') + (block ? opts.separator : '') : ''; - classProps.push(`${name}(${parameters}){${preblock}${block}}`); + let method = `${name}(${parameters}){${preblock}${block}}`; + if (typeof QuintOS != 'undefined' && /(System|alert|prompt|eraseRect)/gm.test(block)) + method = 'async ' + method; + classProps.push(method); } }; diff --git a/jdk/java/io/PrintStream.js b/jdk/java/io/PrintStream.js index 7c8054e..ea73627 100755 --- a/jdk/java/io/PrintStream.js +++ b/jdk/java/io/PrintStream.js @@ -32,7 +32,7 @@ jdk.imports['java.io.PrintStream'].load = async () => { } printf(format, ...args) { - let str = new Formatter().format(format, args); + let str = String.format(format, args); this.log += str; if (window?.ide) { ide.log.value += str; diff --git a/jdk/java/lang/String.js b/jdk/java/lang/String.js index 0d90454..9882b5b 100755 --- a/jdk/java/lang/String.js +++ b/jdk/java/lang/String.js @@ -1,24 +1,30 @@ -jdk.imports['java.lang.String'].load = async () => {}; -// String is special, I just extended js String prototype -String.prototype.hashCode = () => { - let h = this._hashCode; - if (!h && this.length > 0) { - const val = this; - for (let i = 0; i < this.length; i++) { - h = 31 * h + this.charCodeAt(i); +jdk.imports['java.lang.String'].load = async () => { + const Formatter = await jdk.import('java.util.Formatter'); + + // String is special, I just extended js String prototype + String.prototype.hashCode = function () { + let h = this._hashCode; + if (!h && this.length > 0) { + const val = this; + for (let i = 0; i < this.length; i++) { + h = 31 * h + this.charCodeAt(i); + } + this._hashCode = h; } - this._hashCode = h; - } - return h; + return h; + }; + String.prototype.isEmpty = function () { + return this.length == 0; + }; + String.prototype.contains = function (substr) { + return this.includes(substr); + }; + // static methods + String.valueOf = (c) => { + return c.toString(); + }; + String.format = (format, ...args) => { + return new Formatter().format(format, ...args); + }; + jdk.java.lang.String = String; }; -String.prototype.isEmpty = () => { - return this.length == 0; -}; -String.prototype.contains = (substr) => { - return this.includes(substr); -}; -// static methods -String.valueOf = (c) => { - return c.toString(); -}; -jdk.java.lang.String = String; diff --git a/jdk/java/util/AbstractList.js b/jdk/java/util/AbstractList.js index 84c37d8..b9a5fa5 100755 --- a/jdk/java/util/AbstractList.js +++ b/jdk/java/util/AbstractList.js @@ -2,9 +2,9 @@ jdk.imports['java.util.AbstractList'].load = async () => { const Itr = await jdk.import('java.util.Itr'); class AbstractList { - constructor() { + constructor(content) { // TODO - this.content = []; + this.content = content || []; } addAll(index, vals) { diff --git a/jdk/java/util/Arrays.js b/jdk/java/util/Arrays.js index 17b5bf8..fd7d3a3 100755 --- a/jdk/java/util/Arrays.js +++ b/jdk/java/util/Arrays.js @@ -1,16 +1,20 @@ jdk.imports['java.util.Arrays'].load = async () => { - class Arrays { - fill(data, begin, nbElem, param) { - const max = begin + nbElem; - for (let i = begin; i < max; i++) { - data[i] = param; - } + let AbstractList = await jdk.import('java.util.AbstractList'); + + class Arrays {} + Arrays.fill = (data, begin, nbElem, param) => { + const max = begin + nbElem; + for (let i = begin; i < max; i++) { + data[i] = param; } - copyOf(original, newLength, ignore) { - const copy = new Array(newLength); - jdk.java.lang.System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); - return copy; - } - } + }; + Arrays.copyOf = (original, newLength, ignore) => { + const copy = new Array(newLength); + jdk.java.lang.System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); + return copy; + }; + Arrays.asList = (array) => { + return new AbstractList(array); + }; jdk.java.util.Arrays = Arrays; }; diff --git a/jdk/java/util/Collections.js b/jdk/java/util/Collections.js index 1a75d89..06af7ac 100755 --- a/jdk/java/util/Collections.js +++ b/jdk/java/util/Collections.js @@ -1,17 +1,18 @@ jdk.imports['java.util.Collections'].load = async () => { - class Collections { - sort(list) { - if (!list.size()) return; - if (list.get(0).compareTo) { - list.sort(list.get(0).compareTo); - } else { - list.sort(); - } + class Collections {} + + Collections.sort = (list) => { + if (!list.size()) return; + if (list.get(0).compareTo) { + list.sort(list.get(0).compareTo); + } else { + list.sort(); } - swap(list, i, j) { - const l = list; - l.set(i, l.set(j, l.get(i))); - } - } + }; + + Collections.swap = (list, i, j) => { + const l = list; + l.set(i, l.set(j, l.get(i))); + }; jdk.java.util.Collections = Collections; }; diff --git a/package.json b/package.json index b01f3bd..689a75d 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "java2js", - "version": "1.0.7", + "version": "1.0.8", "description": "Converts Java to JavaScript with support for p5.js and QuintOS.", - "main": "java2js.js", + "main": "jdk.js", "scripts": { "start": "open demo.html", "test": "echo \"Error: no test specified\" && exit 1",