Skip to content

Commit 08e3f50

Browse files
committed
Merge branch 'arrays'
Including updated support for ArrayLiterals. User can now write array literals in code. ArrayLiterals are now constructed slightly more efficiently using temps. Additionally INT_MIN and INT_MAX limitations are now respected by IntLiterals.
2 parents 081cc2a + 3d8a045 commit 08e3f50

36 files changed

+479
-162
lines changed

src/Compiler.java

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,34 +92,27 @@ public static void main(String[] args) {
9292
*/
9393
static void compile(String inputFile, CommandLine cmd) {
9494
String [] input_files = {inputFile, "src/Runtime.j"};
95-
ArrayList<ClassType> class_list = new ArrayList<ClassType>();
9695
Source fake = new JavaSource(null, "<MJCInternal>", null);
9796
Position fake_pos = new SourcePosition(fake, 0, 0);
98-
for (Type p : Type.getArrayPrimitives()) {
99-
class_list.add(
100-
new ArrayType(new Modifiers(fake_pos), new Id(fake_pos, p.toString()), p));
101-
}
10297
Handler handler = new SimpleHandler();
98+
Context context = new Context(fake_pos, handler);
99+
103100
for (String i : input_files) {
104101
try {
105102
Reader reader = new FileReader(i);
106103
Source source = new JavaSource(handler, i, reader);
107104
MjcLexer lexer = new MjcLexer(handler, source);
108105
syntax.Parser parser = new syntax.Parser(handler, lexer);
109-
if (parser.getClasses() != null) {
110-
class_list.addAll(Arrays.asList(parser.getClasses()));
111-
}
106+
parser.setContext(context);
107+
parser.parseNow();
112108
} catch (FileNotFoundException e) {
113109
handler.report(new Failure("Cannot open input file " +
114110
i));
115111
}
116112
}
117-
118-
ClassType [] classes = class_list.toArray(new ClassType[0]);
119113
MethEnv main = null;
120-
Context context = new Context(fake_pos, handler, classes);
121114
if ((main = context.check()) != null) {
122-
classes = context.getClasses();
115+
ClassType [] classes = context.getClasses();
123116
if (cmd.hasOption("x")) {
124117
String assemblyFile = cmd.getOptionValue("x");
125118
Assembly assembly = Assembly.assembleToFile(assemblyFile);

src/Runtime.j

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ class Exception {
1212
MJC.die();
1313
}
1414
public static void throwLoc(String file, int lineno, String message) {
15-
String [] items = new String[3];
16-
items[0] = file;
17-
items[1] = Integer.toString(lineno);
18-
items[2] = message;
15+
String [] items = new String[] {
16+
file,
17+
Integer.toString(lineno),
18+
message
19+
};
1920
Exception.throw(String.format("%:% %", items));
2021
}
2122
}
@@ -99,9 +100,10 @@ class ClassPool {
99100
System.out.println(Integer.toString(used));
100101

101102
while (x < used) {
102-
String [] items = new String[2];
103-
items[0] = pool[x].getName();
104-
items[1] = Integer.toString(pool[x].getClassRefId());
103+
String [] items = new String[] {
104+
pool[x].getName(),
105+
Integer.toString(pool[x].getClassRefId())
106+
};
105107
System.out.println(String.format("Name: % Id: %", items));
106108
x = x + 1;
107109
}
@@ -137,9 +139,10 @@ class Array {
137139
return true;
138140
} else {
139141
String msg = "";
140-
String [] items = new String[2];
141-
items[0] = Integer.toString(index);
142-
items[1] = Integer.toString(length);
142+
String [] items = new String[] {
143+
Integer.toString(index),
144+
Integer.toString(length)
145+
};
143146
Exception.throwLoc(filename, lineno,
144147
String.format("Array access out of bounds (index %, length %).", items));
145148
return false;
@@ -252,28 +255,11 @@ class Boolean {
252255

253256
class Integer {
254257
public static char digitToChar(int x) {
255-
if (x == 0) {
256-
return '0';
257-
} else if (x == 1) {
258-
return '1';
259-
} else if (x == 2) {
260-
return '2';
261-
} else if (x == 3) {
262-
return '3';
263-
} else if (x == 4) {
264-
return '4';
265-
} else if (x == 5) {
266-
return '5';
267-
} else if (x == 6) {
268-
return '6';
269-
} else if (x == 7) {
270-
return '7';
271-
} else if (x == 8) {
272-
return '8';
273-
} else if (x == 9) {
274-
return '9';
258+
String digits = "0123456789";
259+
if (x < digits.length()) {
260+
return digits.charAt(x);
275261
} else {
276-
System.out.println("Digit not between 0-9");
262+
Exception.throw("Digit not between 0-9");
277263
}
278264
return 'X';
279265
}

src/checker/Checker.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,15 @@ public static void main(String[] args) {
5656
*/
5757
static void check(Handler handler, Reader reader, String inputFile) {
5858
Source fake = new JavaSource(null, "<MJCInternal>", null);
59+
ClassType [] classes = new ClassType[] {};
5960
Position fake_pos = new SourcePosition(fake, 0, 0);
61+
Context context = new Context(fake_pos, handler);
6062
Source source = new JavaSource(handler, inputFile, reader);
6163
MjcLexer lexer = new MjcLexer(handler, source);
6264
Parser parser = new Parser(handler, lexer);
63-
ClassType[] classes = parser.getClasses();
64-
if (new Context(fake_pos, handler, classes).check() != null) {
65+
parser.setContext(context);
66+
parser.parseNow();
67+
if (context.check() != null) {
6568
System.out.println(
6669
"No static errors found in \"" + inputFile + "\"");
6770
}

src/checker/Context.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
/** Provides a representation for contexts used during type checking.
3131
*/
3232
public final class Context extends Phase {
33-
private ClassType[] classes;
33+
private ArrayList<ClassType> classes;
3434
private ClassType currClass;
3535
private MethEnv currMethod;
3636
private int localBytes;
@@ -40,13 +40,16 @@ public final class Context extends Phase {
4040
private int staticStringCount;
4141
private Id static_class_id;
4242

43-
public Context(Position pos, Handler handler, ClassType[] classes) {
43+
public Context(Position pos, Handler handler) {
4444
super(handler);
45-
this.classes = classes;
4645
this.pos = pos;
4746
this.uniqueStrings = new Hashtable<String, StringLiteral>();
4847
this.staticStringCount = 0;
4948
this.static_class_id = new Id(pos, "MJCStatic");
49+
this.classes = new ArrayList<ClassType>();
50+
}
51+
public void addClass(ClassType cls) {
52+
classes.add(cls);
5053
}
5154
public StringLiteral [] getUniqueStrings() {
5255
return uniqueStrings.values().toArray(new StringLiteral[0]);
@@ -62,14 +65,14 @@ public StringLiteral addStringLiteral(StringLiteral s) {
6265
}
6366

6467
public ClassType [] getClasses() {
65-
return classes;
68+
return classes.toArray(new ClassType[0]);
6669
}
6770
/** Look for the definition of a class by its name.
6871
*/
6972
public ClassType findClass(String name) {
70-
for (int i = 0; i < classes.length; i++) {
71-
if (name.equals(classes[i].getId().getName())) {
72-
return classes[i];
73+
for (ClassType c : classes) {
74+
if (name.equals(c.getId().getName())) {
75+
return c;
7376
}
7477
}
7578
return null;
@@ -126,18 +129,19 @@ && checkClasses()
126129
* in the input program.
127130
*/
128131
private boolean checkClasses() {
129-
ClassType[] classes = this.classes;
130-
for (int i = classes.length - 1; i >= 0; i--) {
132+
for (int i = classes.size() - 1; i >= 0; i--) {
133+
ClassType c_i = classes.get(i);
131134
for (int j = 0; j < i; j++) {
132-
if (classes[i].getId().sameId(classes[j].getId())) {
133-
report(new Failure(classes[i].getPos(),
135+
ClassType c_j = classes.get(j);
136+
if (c_i.getId().sameId(c_j.getId())) {
137+
report(new Failure(c_i.getPos(),
134138
"Multiple definitions for class " +
135-
classes[i].getId()));
139+
c_i.getId()));
136140
break;
137141
}
138142
}
139143
try {
140-
classes[i].checkClass(this);
144+
c_i.checkClass(this);
141145
} catch (Diagnostic d) {
142146
report(d);
143147
return noFailures();
@@ -203,14 +207,7 @@ private boolean checkClasses() {
203207
null, new Block(pos, static_body.toArray(new Statement[0]))).link(decls);
204208

205209
staticClass = new ClassType(m, static_class_id, null, new Type[0], decls);
206-
ClassType [] new_classes = new ClassType[classes.length + 1];
207-
int x = 0;
208-
for (ClassType c : classes) {
209-
new_classes[x] = c;
210-
x++;
211-
}
212-
new_classes[classes.length] = staticClass;
213-
this.classes = new_classes;
210+
classes.add(staticClass);
214211
try {
215212
staticClass.checkClass(this);
216213
} catch (Diagnostic d) {
@@ -226,10 +223,9 @@ private boolean checkClasses() {
226223
* methods) of the classes in this program.
227224
*/
228225
private boolean checkMembers() {
229-
ClassType[] classes = this.classes;
230-
for (int i = 0; i < classes.length; i++) {
231-
setCurrClass(classes[i]);
232-
classes[i].checkMembers(this);
226+
for (ClassType c : classes) {
227+
setCurrClass(c);
228+
c.checkMembers(this);
233229
}
234230
setCurrClass(null);
235231
return noFailures();

src/checker/MethEnv.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ public void compileInvocation(Assembly a, Args args, int free) {
342342
if (isStatic()) {
343343
a.call(methName(a), free, size);
344344
} else {
345+
a.unspill(0);
345346
a.call(a.aindirect(a.reg(0)), free, size);
346347
}
347348
}

src/codegen/Assembly.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,18 @@ public void unspill(int free) {
127127
}
128128
}
129129

130+
public int spillTo(int free, String target_reg) {
131+
int orig_free = free;
132+
while (!target_reg.equals(reg(free))) {
133+
spill(++free);
134+
}
135+
return free;
136+
}
137+
public void unspillTo(int free, int orig_free) {
138+
while (free > orig_free) {
139+
unspill(free--);
140+
}
141+
}
130142
public void spillAll(int free) {
131143
int toSpill = Math.min(free, numRegs - 1);
132144
for (int i = 1; i <= toSpill; i++) {
@@ -176,6 +188,34 @@ public void loadThis(int size, int free) {
176188
emit("movl", indirect(thisOffset(size), "%ebp"), reg(free));
177189
}
178190

191+
private String whereIsTmp(int x86_tmp, int free) {
192+
int diff = free - x86_tmp;
193+
if (diff < 0) {
194+
throw new RuntimeException("Saved Tmp is higher than stack free");
195+
} else if (diff < numRegs) {
196+
return reg(x86_tmp);
197+
} else {
198+
return indirect((diff - numRegs) * WORDSIZE, "%esp");
199+
}
200+
}
201+
/*loads the value from tmp into free */
202+
public void loadTmp(int x86_tmp, int free) {
203+
String where = whereIsTmp(x86_tmp, free);
204+
if (!where.equals(reg(free))) {
205+
emit("movl", where, reg(free));
206+
} else {
207+
/* oddly, it's already in the correct reg */
208+
}
209+
}
210+
211+
public void setTmp(int x86_tmp, int free) {
212+
String where = whereIsTmp(x86_tmp, free);
213+
if (!where.equals(reg(free))) {
214+
emit("movl", reg(free), where);
215+
} else {
216+
/* oddly, it's already in the correct reg */
217+
}
218+
}
179219
//- emit individual instructions, with varying numbers of arguments ------
180220

181221
public void emit(String op) {

src/interp/Interp.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ public static void interp(Reader reader, String description,
6060
Source fake = new JavaSource(null, "<MJCInternal>", null);
6161
Position fake_pos = new SourcePosition(fake, 0, 0);
6262
Parser parser = new Parser(handler, lexer);
63-
ClassType[] classes = parser.getClasses();
64-
Context context = new Context(fake_pos, handler, classes);
63+
Context context = new Context(fake_pos, handler);
64+
parser.setContext(context);
65+
parser.parseNow();
6566
MethEnv main = context.check();
6667
MethEnv init = context.findClass("MJCStatic").findMethod("init");
6768
if (main != null) {

src/lexer/MjcLexer.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,15 +333,15 @@ private int identifier() { // Assumes isJavaIdentifierStart(c)
333333

334334
//- Numeric integer literals ----------------------------------------------
335335

336-
private int number() { // Assumes c is a digit
337-
int n = 0;
338-
int d = Character.digit((char)c, 10);
336+
private int number() {
337+
// We defer computing the value of the intliteral until later
338+
// to allow min and max int values (minus sign may be added later).
339+
StringBuilder b = new StringBuilder();
339340
do {
340-
n = 10 * n + d;
341+
b.append((char)c);
341342
nextChar();
342-
d = Character.digit((char)c, 10);
343-
} while (d >= 0);
344-
semantic = new IntLiteral(getPos(), n);
343+
} while ((char)c >= '0' && (char)c <= '9');
344+
semantic = new IntLiteral(getPos(), b.toString());
345345
return token = INTLIT;
346346
}
347347

src/syntax/ArrayAccess.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ public Type typeOf(Context ctxt, VarEnv env) throws Diagnostic {
7171
* leave the result in the specified free variable.
7272
*/
7373
public void compileExpr(Assembly a, int free) {
74+
a.spill(free + 1);
7475
array_check.compileExpr(a, free + 1);
7576
index.compileExpr(a, free);
7677
a.emit("imull", a.immed(array_class.getElementType().getWidth()), a.reg(free));
77-
a.spill(free + 1);
7878
object.compileExpr(a, free + 1);
7979
FieldEnv f = array_class.findField("array");
8080
a.emit("movl", a.indirect(f.getOffset(), a.reg(free + 1)), a.reg(free + 1));
@@ -87,8 +87,8 @@ public void compileExpr(Assembly a, int free) {
8787
* this expression.
8888
*/
8989
void saveVar(Assembly a, int free) {
90-
array_check.compileExpr(a, free + 1);
9190
a.spill(free + 1);
91+
array_check.compileExpr(a, free + 1);
9292
index.compileExpr(a, free + 1);
9393
a.emit("imull", a.immed(array_class.getElementType().getWidth()),
9494
a.reg(free + 1));
@@ -98,6 +98,7 @@ void saveVar(Assembly a, int free) {
9898
a.emit("movl", a.indirect(f.getOffset(), a.reg(free + 2)), a.reg(free + 2));
9999
a.emit("addl", a.reg(free + 1), a.reg(free + 2));
100100
a.emit("movl", a.reg(free), a.indirect(0, a.reg(free + 2)));
101+
a.unspill(free + 2);
101102
a.unspill(free + 1);
102103
}
103104

0 commit comments

Comments
 (0)