Skip to content

Commit 95947af

Browse files
author
Rosnec
committed
Successfully compiling all MiniJava programs and tail recursion.
Success! Now I just need to clean up a bit.
1 parent a41f44b commit 95947af

5 files changed

Lines changed: 122 additions & 24 deletions

File tree

doc/Simple.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
class Simple {
22
public static void main(String[] args) {
33
{
4+
System.out.println(new C().f(10));
5+
System.out.println(new C().arr(13));
46
System.out.println(new C().fac(10));
57
System.out.println(new C().fac_rec(10));
68
System.out.println(new C().sum(100));
@@ -9,12 +11,26 @@ public static void main(String[] args) {
911
}
1012

1113
class C {
12-
int x;
14+
public int f(int n) {
15+
return this.f_iter(n, 1);
16+
}
17+
18+
public int f_iter(int n, int acc) {
19+
recur (1 < n) ? (n-1, n*acc) : n*acc;
20+
}
21+
22+
public int arr(int n) {
23+
int[] a;
24+
25+
a = new int[n];
26+
27+
return a.length;
28+
}
29+
1330
public int fac(int n) {
1431
int acc;
1532

1633
acc = 1;
17-
x = 2;
1834

1935
while (0 < n) {
2036
acc = acc * n;

project.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(defproject mini-java "0.2.2-SNAPSHOT"
1+
(defproject mini-java "0.2.2"
22
:description "A MiniJava compiler implemented in Clojure."
33
:url "https://github.com/dwysocki/mini-java"
44
:license {:name "MIT License"

src/mini_java/ast.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@
194194
children
195195
(take-nth 2) ; ignore commas
196196
(map ast)
197-
(map (fn [i arg] (assoc arg :index i))
197+
(map (fn [i arg] (assoc arg :arg-index i))
198198
(range))))
199199

200200
(defmethod ast :formal-parameter [node]
@@ -237,7 +237,7 @@
237237

238238
(defmethod ast :array-length-expression [node]
239239
(with-line-and-column node :array-length-expression
240-
(ast (.getChild node 0))))
240+
{:array (ast (.getChild node 0))}))
241241

242242
(defmethod ast :method-call-expression [node]
243243
(with-line-and-column node :method-call-expression

src/mini_java/code_gen.clj

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"(" (arg-types (:args method)) ")"))
5151

5252
(defn- make-method [method]
53-
(Method/getMethod (method-signature method)))
53+
(Method/getMethod (method-signature method)
54+
true))
5455

5556
(defn- make-class
5657
([cw class-name]
@@ -62,13 +63,16 @@
6263

6364
(defn- make-constructor
6465
([cw]
65-
(make-constructor cw nil nil))
66-
([cw fields class-type]
66+
(make-constructor cw obj-type))
67+
([cw parent-type]
6768
(let [init-gen (GeneratorAdapter. Opcodes/ACC_PUBLIC init nil nil cw)]
6869
(doto init-gen
6970
(.loadThis)
70-
(.invokeConstructor obj-type init))
71-
(when fields
71+
(.invokeConstructor parent-type init))
72+
73+
;; probably don't need this ever
74+
;; delete when more certain
75+
#_(when fields
7276
(doseq [[name field] fields]
7377
(doto init-gen
7478
(.loadThis)
@@ -137,12 +141,17 @@
137141
(defmethod generate :class-declaration [class scopes]
138142
(let [cw (make-class-writer)
139143
class-type (-> class :name type->Type)
144+
parent-type (if-let [parent (:parent class)]
145+
(type->Type parent)
146+
obj-type)
140147
_ (make-class cw (:name class) (:parent class))
141148
_ (generate-fields (:vars class) cw)
142-
init (make-constructor cw (:vars class) class-type)
149+
init (make-constructor cw parent-type)
143150
scopes (assoc scopes
144151
:class class
145-
:class-type class-type)]
152+
:class-type class-type
153+
:parents (semantics/parent-seq class
154+
(:class-table scopes)))]
146155

147156

148157
;; generate methods
@@ -159,12 +168,12 @@
159168
;; create a new local in the method generator
160169
index (.newLocal method-gen type)]
161170
;; store the index in the var
162-
(assoc var :index index)))
171+
(assoc var :ref-index index)))
163172

164173
(defn- generate-locals [vars method-gen]
165174
(-> (fn [m [name var]]
166175
(assoc m
167-
name (if-not (:index var)
176+
name (if-not (:arg-index var)
168177
(generate-local var method-gen)
169178
var)))
170179
(reduce vars vars)))
@@ -218,7 +227,7 @@
218227
(.mark method-gen start-label)
219228
;; push predicate
220229
(generate (:pred statement) scopes method-gen)
221-
;; test predicate
230+
;; test predicate, go past body if false
222231
(.ifZCmp method-gen GeneratorAdapter/EQ end-label)
223232
;; while body
224233
(generate (:body statement) scopes method-gen)
@@ -231,25 +240,58 @@
231240
"Generate a variable assignment statement.
232241
233242
TODO: Only works with locals, fix to work with class fields too."
234-
;; put source of assignment on stack
235-
(generate (:source statement) scopes method-gen)
236243
(let [target-name (:target statement)]
237244
(or
238-
(when-let [target (locate-arg target-name scopes)]
245+
(when-let [target (locate-arg target-name scopes)]
246+
;; put source of assignment on stack
247+
(generate (:source statement) scopes method-gen)
239248
(.storeArg method-gen
240-
(:index target))
249+
(:arg-index target))
241250
true)
242251
(when-let [target (locate-local target-name scopes)]
252+
;; put source of assignment on stack
253+
(generate (:source statement) scopes method-gen)
243254
(.storeLocal method-gen
244-
(:index target)
255+
(:ref-index target)
245256
(-> target :type type->Type))
246257
true)
247258
(let [target (semantics/locate-var target-name scopes)]
259+
(.loadThis method-gen)
260+
;; put source of assignment on stack
261+
(generate (:source statement) scopes method-gen)
262+
;; store field
248263
(.putField method-gen
249264
(:class-type scopes)
250265
target-name
251266
(-> target :type type->Type))))))
252267

268+
(defmethod generate :array-assign-statement [statement scopes method-gen]
269+
"Generate an array assignment statement."
270+
271+
(let [target-name (:target statement)]
272+
(or ;; put array reference on stack
273+
(when-let [target (locate-arg target-name scopes)]
274+
(.loadArg method-gen
275+
(:arg-index target))
276+
true)
277+
(when-let [target (locate-local target-name scopes)]
278+
(.loadLocal method-gen
279+
(:ref-index target)
280+
(-> target :type type->Type))
281+
true)
282+
(let [target (semantics/locate-var target-name scopes)]
283+
(.loadThis method-gen)
284+
(.getField method-gen
285+
(:class-type scopes)
286+
target-name
287+
(-> target :type type->Type))))
288+
;; put array index on stack
289+
(generate (:index statement) scopes method-gen)
290+
;; put value to store in array on stack
291+
(generate (:source statement) scopes method-gen)
292+
;; store value in array
293+
(.arrayStore method-gen Type/INT_TYPE)))
294+
253295
(defmethod generate :print-statement [statement scopes method-gen]
254296
(.getStatic method-gen
255297
(Type/getType System)
@@ -264,6 +306,40 @@
264306
(generate (:return-value statement) scopes method-gen)
265307
(.returnValue method-gen))
266308

309+
(defn- rebind-arg [argument index scopes method-gen]
310+
(generate argument scopes method-gen)
311+
(.storeArg method-gen index))
312+
313+
(defmethod generate :recur-statement [statement scopes method-gen start-label]
314+
(let [base-label (.newLabel method-gen)]
315+
(generate (:pred statement) scopes method-gen)
316+
;; if predicate is false, goto base case
317+
(.ifZCmp method-gen GeneratorAdapter/EQ base-label)
318+
;; when predicate is true, evaluate arguments, rebind and recur:
319+
;; evaluate arguments
320+
(doseq [arg (:args statement)]
321+
(generate arg scopes method-gen))
322+
;; rebind arguments
323+
(doseq [index (-> statement :args count range reverse)]
324+
(.storeArg method-gen index))
325+
;; recur
326+
(.goTo method-gen start-label)
327+
;; base case
328+
(.mark method-gen base-label)
329+
(generate (:base statement) scopes method-gen)
330+
(.returnValue method-gen)))
331+
332+
(defmethod generate :array-access-expression [expression scopes method-gen]
333+
(generate (:array expression) scopes method-gen)
334+
(generate (:index expression) scopes method-gen)
335+
(.arrayLoad method-gen Type/INT_TYPE))
336+
337+
(defmethod generate :array-length-expression [expression scopes method-gen]
338+
;; load array reference on stack
339+
(generate (:array expression) scopes method-gen)
340+
;; load length of array reference on stack
341+
(.arrayLength method-gen))
342+
267343
(defn- binary-expression [expression scopes method-gen]
268344
(generate (:left expression) scopes method-gen)
269345
(generate (:right expression) scopes method-gen))
@@ -310,6 +386,11 @@
310386
(unary-expression expression scopes method-gen)
311387
(.math method-gen GeneratorAdapter/NEG Type/INT_TYPE))
312388

389+
(defmethod generate :array-instantiation-expression [expression scopes
390+
method-gen]
391+
(generate (:size expression) scopes method-gen)
392+
(.newArray method-gen Type/INT_TYPE))
393+
313394
(defmethod generate :method-call-expression [expression scopes method-gen]
314395
;; push caller onto stack
315396
(generate (:caller expression) scopes method-gen)
@@ -325,7 +406,7 @@
325406
signature (method-signature method)]
326407
(.invokeVirtual method-gen
327408
(Type/getObjectType caller-type)
328-
(Method/getMethod signature))))
409+
(Method/getMethod signature true))))
329410

330411
(defmethod generate :int-lit-expression [expression scopes method-gen]
331412
(.push method-gen (:value expression)))
@@ -342,14 +423,15 @@
342423
(or
343424
;; load method argument
344425
(when-let [var (locate-arg (:id expression) scopes)]
345-
(.loadArg method-gen (:index var))
426+
(.loadArg method-gen (:arg-index var))
346427
true)
347428
;; load local variable
348429
(when-let [var (locate-local (:id expression) scopes)]
349-
(.loadLocal method-gen (:index var))
430+
(.loadLocal method-gen (:ref-index var))
350431
true)
351432
;; load non-static field
352433
(let [field (semantics/locate-var (:id expression) scopes)]
434+
(.loadThis method-gen)
353435
(.getField method-gen
354436
;; field owner
355437
(:class-type scopes)

src/mini_java/static_semantics.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@
173173
:body (:body class)}}}
174174
(with-meta (meta class))))
175175

176-
(defn- parent-seq [class class-table]
176+
(defn parent-seq [class class-table]
177177
"Returns a lazy seq of all parents of the given class."
178178
(lazy-seq
179179
(when-let [parent-name (:parent class)]

0 commit comments

Comments
 (0)