Skip to content

Commit fa4b27e

Browse files
committed
Initial version working
1 parent c9e3247 commit fa4b27e

File tree

5 files changed

+209
-129
lines changed

5 files changed

+209
-129
lines changed

src/main/java/wyjs/Main.java

Lines changed: 134 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,152 @@
1313
// limitations under the License.
1414
package wyjs;
1515

16+
import java.io.BufferedReader;
1617
import java.io.File;
18+
import java.io.FileInputStream;
1719
import java.io.FileOutputStream;
1820
import java.io.IOException;
21+
import java.io.InputStream;
22+
import java.io.InputStreamReader;
23+
import java.io.Reader;
24+
import java.util.ArrayList;
25+
import java.util.Arrays;
26+
import java.util.List;
27+
import java.util.Map;
1928

29+
import wycc.util.OptArg;
2030
import wycc.util.Trie;
21-
import wyil.io.WyilFileWriter;
22-
import wyil.lang.WyilFile;
2331
import wyjs.core.JavaScriptFile;
32+
import wyjs.core.JavaScriptFile.NativeDeclaration;
33+
import wyjs.core.JavaScriptFile.Standard;
2434
import wyjs.io.JavaScriptFilePrinter;
35+
import wyjs.tasks.JavaScriptCompileTask;
2536

2637
public class Main {
38+
/**
39+
* Determine the JavaScript standard to use.
40+
*/
41+
private Standard standard = Standard.ES6;
42+
/**
43+
* Destination directory of Wyil files.
44+
*/
45+
private File wyildir = new File(".");
46+
/**
47+
* Destination directory of Wyil files.
48+
*/
49+
private File jsdir = new File(".");
50+
/**
51+
* List of source files.
52+
*/
53+
private List<Trie> sources = new ArrayList<>();
54+
/**
55+
* Determine target filename.
56+
*/
57+
private Trie target = Trie.fromString("main");
58+
/**
59+
* List of JavaScript files to include.
60+
*/
61+
private List<File> includes = new ArrayList<>();
62+
63+
public Main addSource(Trie source) {
64+
this.sources.add(source);
65+
return this;
66+
}
2767

68+
public Main setStandard(Standard standard) {
69+
this.standard = standard;
70+
return this;
71+
}
2872

29-
// public JavaScriptFile readJavaScriptFile(Trie p, InputStream inputStream, Content.Registry registry) throws IOException {
30-
// // NOTE: this is strictly a hack at this time as its unclear what the best
31-
// // alternative option is. Specifically, parsing JavaScriptFiles is not something
32-
// // I'm contemplating right now :)
33-
// Reader reader = new InputStreamReader(inputStream);
34-
// BufferedReader in = new BufferedReader(reader);
35-
//
36-
// StringBuilder text = new StringBuilder();
37-
// int len = 0;
38-
// char[] buf = new char[1024];
39-
// while ((len = in.read(buf)) != -1) {
40-
// text.append(buf, 0, len);
41-
// }
42-
// // Finally, construct the native declaration
43-
// NativeDeclaration d = new NativeDeclaration(text.toString());
44-
// //
45-
// JavaScriptFile js = new JavaScriptFile(p, Collections.EMPTY_LIST, true, Standard.ES6);
46-
// // Append our native declarations.
47-
// js.declarations.add(d);
48-
// return js;
49-
// }
73+
public Main setTarget(Trie target) {
74+
this.target = target;
75+
return this;
76+
}
5077

78+
public Main setWyilDir(File wyildir) {
79+
this.wyildir = wyildir;
80+
return this;
81+
}
82+
83+
public Main setJsDir(File jsdir) {
84+
this.jsdir = jsdir;
85+
return this;
86+
}
87+
88+
public boolean run() throws IOException {
89+
// Construct compile task
90+
JavaScriptCompileTask task = new JavaScriptCompileTask().setTarget(target).setStandard(standard);
91+
// Add sources
92+
for(Trie source : sources) {
93+
// Extract source file
94+
task.addSource(wyc.Compiler.readWyilFile(wyildir, source));
95+
}
96+
for(File include : includes) {
97+
FileInputStream fin = new FileInputStream(include);
98+
JavaScriptFile jsf = readJavaScriptFile(fin);
99+
fin.close();
100+
task.addInclude(jsf);
101+
}
102+
JavaScriptFile target = task.run();
103+
// Write out binary target
104+
wyjs.Main.writeJavaScriptFile(this.target, target, jsdir);
105+
// Unsure how it can fail!
106+
return true;
107+
}
108+
109+
/**
110+
* Command-line options
111+
*/
112+
private static final OptArg[] OPTIONS = {
113+
// Standard options
114+
new OptArg("verbose","v","set verbose output"),
115+
new OptArg("standard","s",OptArg.STRING,"set JavaScript standard","ES6"),
116+
new OptArg("output","o",OptArg.STRING,"set output file","main"),
117+
new OptArg("wyildir", OptArg.FILEDIR, "Specify where to place binary (WyIL) files", new File(".")),
118+
new OptArg("jsdir", OptArg.FILEDIR, "Specify where to place JavaScript files", new File("."))
119+
};
120+
//
121+
public static void main(String[] _args) throws IOException {
122+
List<String> args = new ArrayList<>(Arrays.asList(_args));
123+
Map<String, Object> options = OptArg.parseOptions(args, OPTIONS);
124+
//
125+
File wyildir = (File) options.get("wyildir");
126+
File jsdir = (File) options.get("jsdir");
127+
Trie target = Trie.fromString((String) options.get("output"));
128+
Standard standard = Standard.valueOf((String) options.get("standard"));
129+
// Construct Main object
130+
Main main = new Main().setStandard(standard).setWyilDir(wyildir).setJsDir(jsdir).setTarget(target);
131+
// Add source files
132+
for (String s : args) {
133+
main.addSource(Trie.fromString(s));
134+
}
135+
// Run the compiler!
136+
boolean result = main.run();
137+
// Produce exit code
138+
System.exit(result ? 0 : 1);
139+
}
140+
141+
public JavaScriptFile readJavaScriptFile(InputStream inputStream) throws IOException {
142+
// NOTE: this is strictly a hack at this time as its unclear what the best
143+
// alternative option is. Specifically, parsing JavaScriptFiles is not something
144+
// I'm contemplating right now :)
145+
Reader reader = new InputStreamReader(inputStream);
146+
BufferedReader in = new BufferedReader(reader);
147+
148+
StringBuilder text = new StringBuilder();
149+
int len = 0;
150+
char[] buf = new char[1024];
151+
while ((len = in.read(buf)) != -1) {
152+
text.append(buf, 0, len);
153+
}
154+
// Finally, construct the native declaration
155+
NativeDeclaration d = new NativeDeclaration(text.toString());
156+
//
157+
JavaScriptFile js = new JavaScriptFile(true, Standard.ES6);
158+
// Append our native declarations.
159+
js.getDeclarations().add(d);
160+
return js;
161+
}
51162

52163
/**
53164
* Write a given WyilFile to disk using the given directory as a root.

src/main/java/wyjs/core/JavaScriptFile.java

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ public enum Standard {
4848
//
4949
// =========================================================================
5050

51-
/**
52-
* The filename of this artifact
53-
*/
54-
private final Trie path;
55-
/**
56-
* The source files that were combined into this file.
57-
*/
58-
private final List<WyilFile> sources;
5951
/**
6052
* Indicate whether or not to use strict mode.
6153
*/
@@ -69,13 +61,11 @@ public enum Standard {
6961
*/
7062
private List<Declaration> declarations;
7163

72-
public JavaScriptFile(Trie path, List<WyilFile> sources, Standard standard) {
73-
this(path, sources, true, standard);
64+
public JavaScriptFile(Standard standard) {
65+
this(true, standard);
7466
}
7567

76-
public JavaScriptFile(Trie path, List<WyilFile> sources, boolean strictMode, Standard standard) {
77-
this.path = path;
78-
this.sources = new ArrayList<>(sources);
68+
public JavaScriptFile(boolean strictMode, Standard standard) {
7969
this.strictMode = strictMode;
8070
this.standard = standard;
8171
this.declarations = new ArrayList<>();
@@ -118,18 +108,10 @@ public boolean bigInt() {
118108
return standard == Standard.ES6_BIGINT;
119109
}
120110

121-
public Trie getPath() {
122-
return path;
123-
}
124-
125111
public List<Declaration> getDeclarations() {
126112
return declarations;
127113
}
128114

129-
public List<WyilFile> getSourceArtifacts() {
130-
return sources;
131-
}
132-
133115
// =========================================================================
134116
// Static Constructors
135117
// =========================================================================

src/main/java/wyjs/tasks/JavaScriptCompileTask.java

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,82 +13,79 @@
1313
// limitations under the License.
1414
package wyjs.tasks;
1515

16+
import java.util.ArrayList;
1617
import java.util.Arrays;
1718
import java.util.Collections;
1819
import java.util.List;
1920
import wycc.util.Pair;
2021
import wycc.util.Trie;
2122
import wyil.lang.WyilFile;
2223
import wyjs.core.JavaScriptFile;
24+
import wyjs.core.JavaScriptFile.Standard;
2325

2426
public class JavaScriptCompileTask {
25-
/**
26-
* The set of source files that this task will compiler from.
27-
*/
28-
private final Trie source;
2927
/**
3028
* Identifier for target of this build task.
3129
*/
32-
private final Trie target;
30+
private Trie target = Trie.fromString("main");
3331
/**
34-
* Specify whether or not to generate a "strict" JavaScript file.
32+
* The set of source files that this task will compiler from.
3533
*/
36-
private final boolean strict;
34+
private final List<WyilFile> sources = new ArrayList<>();
3735
/**
38-
* Specify JavaScript standard to generate for
36+
* Additional JavaScript files to include in generated file.
3937
*/
40-
private final JavaScriptFile.Standard standard;
38+
private final List<JavaScriptFile> includes = new ArrayList<>();
4139
/**
42-
* Additional JavaScript files to include in generated file.
40+
* Specify whether or not to generate a "strict" JavaScript file.
4341
*/
44-
private final List<WyilFile> wyIncludes;
42+
private boolean strict = true;
4543
/**
46-
* Additional JavaScript files to include in generated file.
44+
* Specify JavaScript standard to generate for
4745
*/
48-
private final List<JavaScriptFile> jsIncludes;
46+
private Standard standard = Standard.ES6;
4947

50-
public JavaScriptCompileTask(Trie target, Trie source, JavaScriptFile.Standard standard) {
51-
this(target, source, true, standard, Collections.emptyList(), Collections.emptyList());
48+
public JavaScriptCompileTask setTarget(Trie target) {
49+
this.target = target;
50+
return this;
5251
}
5352

54-
public JavaScriptCompileTask(Trie target, Trie source, boolean strict, JavaScriptFile.Standard standard,
55-
List<WyilFile> wyIncludes, List<JavaScriptFile> jsIncludes) {
56-
if(target == null) {
57-
throw new IllegalArgumentException("invalid target");
58-
} else if(source == null) {
59-
throw new IllegalArgumentException("invalid source");
60-
}
61-
this.target = target;
62-
this.source = source;
63-
this.strict = strict;
64-
this.standard = standard;
65-
this.wyIncludes = wyIncludes;
66-
this.jsIncludes = jsIncludes;
53+
public JavaScriptCompileTask setStrict(boolean flag) {
54+
this.strict = flag;
55+
return this;
56+
}
57+
58+
public JavaScriptCompileTask setStandard(Standard std) {
59+
this.standard = std;
60+
return this;
61+
}
62+
63+
public JavaScriptCompileTask addSource(WyilFile f) {
64+
this.sources.add(f);
65+
return this;
66+
}
67+
68+
public JavaScriptCompileTask addInclude(JavaScriptFile f) {
69+
this.includes.add(f);
70+
return this;
6771
}
6872

6973
public Trie getPath() {
7074
return target;
7175
}
7276

73-
public Pair<JavaScriptFile, Boolean> compile(WyilFile source) {
77+
public JavaScriptFile run() {
7478
// Construct initial (empty) JavaScript file
75-
JavaScriptFile jsFile = new JavaScriptFile(target, Arrays.asList(source), strict, standard);
76-
// FIXME: this is a fairly temporary solution at the moment which just
77-
// turns the WyIL file directly into a string. A more useful solution
78-
// will be to generate an intermediate file representing JavaScript in
79-
// an AST. This would enable, for example, better support for different
80-
// standards. It would also enable minification, and allow support for
81-
// different module systems (e.g. CommonJS).
82-
new JavaScriptCompiler(jsFile).visitModule(source);
83-
// Process Wyil includes
84-
for (WyilFile i : wyIncludes) {
79+
JavaScriptFile jsFile = new JavaScriptFile(strict, standard);
80+
// Process source files one by one
81+
for (WyilFile i : sources) {
8582
new JavaScriptCompiler(jsFile).visitModule(i);
8683
}
87-
// Process JavaScript includes
88-
for (JavaScriptFile i : jsIncludes) {
84+
// Process additional JavaScript includes
85+
for (JavaScriptFile i : includes) {
8986
jsFile.getDeclarations().addAll(i.getDeclarations());
9087
}
9188
// How could this fail?
92-
return new Pair<>(jsFile, true);
89+
return jsFile;
9390
}
9491
}

src/main/java/wyjs/tasks/JavaScriptCompiler.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static wyil.lang.WyilFile.EXPR_recordborrow;
2626
import static wyil.lang.WyilFile.EXPR_variablecopy;
2727
import static wyil.lang.WyilFile.EXPR_variablemove;
28+
import static wyil.lang.WyilFile.EXPR_staticvariable;
2829
import static wyil.lang.WyilFile.EXPR_tupleinitialiser;
2930
import static wyil.lang.WyilFile.TYPE_array;
3031
import static wyil.lang.WyilFile.TYPE_bool;
@@ -483,6 +484,12 @@ public Term constructVariableAccessLVal(Expr.VariableAccess expr) {
483484
return new JavaScriptFile.VariableAccess(name);
484485
}
485486

487+
@Override
488+
public Term constructStaticVariableAccessLVal(Expr.StaticVariableAccess expr) {
489+
String name = toMangledName(expr.getLink().getTarget());
490+
return new JavaScriptFile.VariableAccess(name);
491+
}
492+
486493
// ====================================================================================
487494
// Expression Constructors
488495
// ====================================================================================
@@ -1984,6 +1991,11 @@ private boolean extractDefinedVariable(LVal lval, Set<Decl.Variable> defs) {
19841991
defs.add(e.getVariableDeclaration());
19851992
return true;
19861993
}
1994+
case EXPR_staticvariable: {
1995+
Expr.StaticVariableAccess e = (Expr.StaticVariableAccess) lval;
1996+
defs.add(e.getLink().getTarget());
1997+
return true;
1998+
}
19871999
default:
19882000
throw new IllegalArgumentException("invalid lval: " + lval);
19892001
}
@@ -2018,7 +2030,8 @@ private void extractUsedVariables(LVal lval, Set<Decl.Variable> uses) {
20182030
break;
20192031
}
20202032
case EXPR_variablecopy:
2021-
case EXPR_variablemove: {
2033+
case EXPR_variablemove:
2034+
case EXPR_staticvariable: {
20222035
// NOTE: nothing to do here, since this variable is being defined.
20232036
break;
20242037
}

0 commit comments

Comments
 (0)