├── .gitignore ├── testcases ├── test26.tig ├── test8.tig ├── test10.tig ├── test13.tig ├── test15.tig ├── test20.tig ├── test9.tig ├── test33.tig ├── test24.tig ├── test25.tig ├── test12.tig ├── test40.tig ├── test31.tig ├── test27.tig ├── test11.tig ├── test35.tig ├── test43.tig ├── test36.tig ├── test41.tig ├── test34.tig ├── test46.tig ├── test1.tig ├── test30.tig ├── test45.tig ├── test32.tig ├── test49.tig ├── test22.tig ├── test44.tig ├── test16.tig ├── test23.tig ├── test2.tig ├── test29.tig ├── test3.tig ├── test37.tig ├── test4.tig ├── test17.tig ├── test28.tig ├── test38.tig ├── test21.tig ├── test6.tig ├── test39.tig ├── test14.tig ├── test7.tig ├── test18.tig ├── test19.tig ├── test47.tig ├── test5.tig ├── test48.tig ├── test42.tig ├── queens.tig └── merge.tig ├── chap4 ├── Absyn │ ├── Dec.java │ ├── Ty.java │ ├── Exp.java │ ├── Var.java │ ├── Absyn.java │ ├── NilExp.java │ ├── BreakExp.java │ ├── IntExp.java │ ├── NameTy.java │ ├── VarExp.java │ ├── ArrayTy.java │ ├── SeqExp.java │ ├── SimpleVar.java │ ├── StringExp.java │ ├── DecList.java │ ├── ExpList.java │ ├── RecordTy.java │ ├── WhileExp.java │ ├── AssignExp.java │ ├── LetExp.java │ ├── FieldVar.java │ ├── CallExp.java │ ├── ForExp.java │ ├── SubscriptVar.java │ ├── ArrayExp.java │ ├── RecordExp.java │ ├── TypeDec.java │ ├── FieldExpList.java │ ├── VarDec.java │ ├── FieldList.java │ ├── OpExp.java │ ├── IfExp.java │ ├── FunctionDec.java │ └── Print.java ├── Parse │ ├── Yylex.class │ ├── Lexer.java │ ├── Main.java │ ├── Token.java │ ├── Parse.java │ └── Grm.cup ├── Symbol │ ├── Symbol.java │ └── Table.java └── ErrorMsg │ └── ErrorMsg.java ├── chap6 ├── Temp │ ├── TempMap.java │ ├── TempList.java │ ├── LabelList.java │ ├── DefaultMap.java │ ├── Temp.java │ ├── CombineMap.java │ └── Label.java └── Util │ └── BoolList.java ├── chap2 ├── Parse │ ├── Lexer.java │ ├── Tiger.lex │ ├── sym.java │ └── Main.java ├── makefile └── ErrorMsg │ └── ErrorMsg.java ├── chap3 ├── Parse │ ├── Lexer.java │ ├── Main.java │ ├── Parse.java │ └── Grm.cup ├── makefile └── ErrorMsg │ └── ErrorMsg.java ├── chap7 └── Tree │ ├── Stm.java │ ├── ExpList.java │ ├── StmList.java │ ├── TEMP.java │ ├── CONST.java │ ├── NAME.java │ ├── LABEL.java │ ├── MEM.java │ ├── EXP.java │ ├── SEQ.java │ ├── ESEQ.java │ ├── CALL.java │ ├── JUMP.java │ ├── BINOP.java │ ├── MOVE.java │ ├── CJUMP.java │ └── Print.java ├── chap9 ├── Assem │ ├── Targets.java │ ├── InstrList.java │ ├── LABEL.java │ ├── MOVE.java │ ├── OPER.java │ └── Instr.java ├── Canon │ ├── StmListList.java │ ├── BasicBlocks.java │ ├── TraceSchedule.java │ └── Canon.java └── Main │ └── Main.java ├── chap5 └── Types │ ├── INT.java │ ├── VOID.java │ ├── STRING.java │ ├── Type.java │ ├── ARRAY.java │ ├── NIL.java │ ├── RECORD.java │ └── NAME.java ├── chap10 ├── Graph │ ├── NodeList.java │ ├── Node.java │ └── Graph.java ├── RegAlloc │ ├── MoveList.java │ └── InterferenceGraph.java └── FlowGraph │ └── FlowGraph.java ├── chap8 └── Canon │ ├── StmListList.java │ ├── BasicBlocks.java │ ├── TraceSchedule.java │ └── Canon.java ├── README.md ├── chap1 ├── prog.java ├── interp.java ├── exer1_1.java └── slp.java └── chap12 └── runtime.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | -------------------------------------------------------------------------------- /testcases/test26.tig: -------------------------------------------------------------------------------- 1 | /* error : integer required */ 2 | 3 | 3 + "var" 4 | -------------------------------------------------------------------------------- /testcases/test8.tig: -------------------------------------------------------------------------------- 1 | /* correct if */ 2 | if (10 > 20) then 30 else 40 3 | -------------------------------------------------------------------------------- /testcases/test10.tig: -------------------------------------------------------------------------------- 1 | /* error : body of while not unit */ 2 | while(10 > 5) do 5+6 3 | -------------------------------------------------------------------------------- /testcases/test13.tig: -------------------------------------------------------------------------------- 1 | /* error: comparison of incompatible types */ 2 | 3 | 3 > "df" 4 | -------------------------------------------------------------------------------- /testcases/test15.tig: -------------------------------------------------------------------------------- 1 | /* error : if-then returns non unit */ 2 | 3 | if 20 then 3 4 | -------------------------------------------------------------------------------- /testcases/test20.tig: -------------------------------------------------------------------------------- 1 | /* error: undeclared variable i */ 2 | 3 | while 10 > 5 do (i+1;()) 4 | -------------------------------------------------------------------------------- /testcases/test9.tig: -------------------------------------------------------------------------------- 1 | /* error : types of then - else differ */ 2 | 3 | if (5>4) then 13 else " " 4 | -------------------------------------------------------------------------------- /testcases/test33.tig: -------------------------------------------------------------------------------- 1 | /* error : unknown type */ 2 | let 3 | var a:= rectype {} 4 | in 5 | 0 6 | end 7 | -------------------------------------------------------------------------------- /chap4/Absyn/Dec.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | abstract public class Dec extends Absyn {} 4 | -------------------------------------------------------------------------------- /chap4/Absyn/Ty.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | abstract public class Ty extends Absyn {} 4 | -------------------------------------------------------------------------------- /testcases/test24.tig: -------------------------------------------------------------------------------- 1 | /* error : variable not array */ 2 | let 3 | var d:=0 4 | in 5 | d[3] 6 | end 7 | 8 | -------------------------------------------------------------------------------- /testcases/test25.tig: -------------------------------------------------------------------------------- 1 | /* error : variable not record */ 2 | let 3 | var d:=0 4 | in 5 | d.f 6 | end 7 | 8 | -------------------------------------------------------------------------------- /chap4/Absyn/Exp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | abstract public class Exp extends Absyn { 4 | } 5 | -------------------------------------------------------------------------------- /chap4/Absyn/Var.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | abstract public class Var extends Absyn { 4 | } 5 | -------------------------------------------------------------------------------- /chap6/Temp/TempMap.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public interface TempMap {public String tempMap(Temp.Temp t);} 4 | 5 | -------------------------------------------------------------------------------- /testcases/test12.tig: -------------------------------------------------------------------------------- 1 | /* valid for and let */ 2 | 3 | let 4 | var a:= 0 5 | in 6 | for i:=0 to 100 do (a:=a+1;()) 7 | end 8 | -------------------------------------------------------------------------------- /testcases/test40.tig: -------------------------------------------------------------------------------- 1 | /* error : procedure returns value */ 2 | let 3 | function g(a:int) = a 4 | in 5 | g(2) 6 | end 7 | 8 | -------------------------------------------------------------------------------- /chap4/Absyn/Absyn.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | abstract public class Absyn { 4 | public int pos; 5 | } 6 | -------------------------------------------------------------------------------- /chap4/Parse/Yylex.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffweiss/modern_compiler_implementation_in_java/HEAD/chap4/Parse/Yylex.class -------------------------------------------------------------------------------- /testcases/test31.tig: -------------------------------------------------------------------------------- 1 | /* error : type constraint and init value differ */ 2 | let 3 | var a:int := " " 4 | in 5 | a 6 | end 7 | -------------------------------------------------------------------------------- /chap4/Parse/Lexer.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | interface Lexer { 4 | public Token nextToken() throws java.io.IOException; 5 | } 6 | -------------------------------------------------------------------------------- /testcases/test27.tig: -------------------------------------------------------------------------------- 1 | /* locals hide globals */ 2 | let 3 | var a:=0 4 | 5 | function g(a:int):int = a 6 | in 7 | g(2) 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test11.tig: -------------------------------------------------------------------------------- 1 | /* error hi expr is not int, and index variable erroneously assigned to. */ 2 | for i:=10 to " " do 3 | i := i - 1 4 | -------------------------------------------------------------------------------- /chap4/Absyn/NilExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class NilExp extends Exp { 4 | public NilExp(int p) {pos=p;} 5 | } 6 | -------------------------------------------------------------------------------- /testcases/test35.tig: -------------------------------------------------------------------------------- 1 | /* error : formals are more then actuals */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g("one") 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test43.tig: -------------------------------------------------------------------------------- 1 | /* initialize with unit and causing type mismatch in addition */ 2 | 3 | let 4 | var a := () 5 | in 6 | a + 3 7 | end 8 | -------------------------------------------------------------------------------- /chap2/Parse/Lexer.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | interface Lexer { 4 | public java_cup.runtime.Symbol nextToken() throws java.io.IOException; 5 | } 6 | -------------------------------------------------------------------------------- /chap3/Parse/Lexer.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | interface Lexer { 4 | public java_cup.runtime.Symbol nextToken() throws java.io.IOException; 5 | } 6 | -------------------------------------------------------------------------------- /testcases/test36.tig: -------------------------------------------------------------------------------- 1 | /* error : formals are fewer then actuals */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g(3,"one",5) 6 | end 7 | -------------------------------------------------------------------------------- /chap4/Absyn/BreakExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class BreakExp extends Exp { 4 | public BreakExp(int p) {pos=p;} 5 | } 6 | -------------------------------------------------------------------------------- /chap7/Tree/Stm.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | abstract public class Stm { 3 | abstract public ExpList kids(); 4 | abstract public Stm build(ExpList kids); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /testcases/test41.tig: -------------------------------------------------------------------------------- 1 | /* local types hide global */ 2 | let 3 | type a = int 4 | in 5 | let 6 | type a = string 7 | in 8 | 0 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /chap9/Assem/Targets.java: -------------------------------------------------------------------------------- 1 | package Assem; 2 | 3 | public class Targets { 4 | public Temp.LabelList labels; 5 | public Targets(Temp.LabelList l) {labels=l;} 6 | } 7 | -------------------------------------------------------------------------------- /testcases/test34.tig: -------------------------------------------------------------------------------- 1 | /* error : formals and actuals have different types */ 2 | let 3 | function g (a:int , b:string):int = a 4 | in 5 | g("one", "two") 6 | end 7 | -------------------------------------------------------------------------------- /testcases/test46.tig: -------------------------------------------------------------------------------- 1 | /* valid rec comparisons */ 2 | let 3 | type rectype = {name:string, id:int} 4 | var b:rectype := nil 5 | in 6 | b = nil; 7 | b <> nil 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test1.tig: -------------------------------------------------------------------------------- 1 | /* an array type and an array variable */ 2 | let 3 | type arrtype = array of int 4 | var arr1:arrtype := arrtype [10] of 0 5 | in 6 | arr1 7 | end 8 | -------------------------------------------------------------------------------- /chap5/Types/INT.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class INT extends Type { 4 | public INT () {} 5 | public boolean coerceTo(Type t) {return (t.actual() instanceof INT);} 6 | } 7 | 8 | -------------------------------------------------------------------------------- /chap5/Types/VOID.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class VOID extends Type { 4 | public VOID () {} 5 | public boolean coerceTo(Type t) {return (t.actual() instanceof VOID);} 6 | } 7 | -------------------------------------------------------------------------------- /testcases/test30.tig: -------------------------------------------------------------------------------- 1 | /* synonyms are fine */ 2 | 3 | let 4 | type a = array of int 5 | type b = a 6 | 7 | var arr1:a := b [10] of 0 8 | in 9 | arr1[2] 10 | end 11 | -------------------------------------------------------------------------------- /chap4/Absyn/IntExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class IntExp extends Exp { 4 | public int value; 5 | public IntExp(int p, int v) {pos=p; value=v;} 6 | } 7 | -------------------------------------------------------------------------------- /chap4/Absyn/NameTy.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class NameTy extends Ty { 4 | public Symbol name; 5 | public NameTy(int p, Symbol n) {pos=p; name=n;} 6 | } 7 | -------------------------------------------------------------------------------- /chap4/Absyn/VarExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class VarExp extends Exp { 4 | public Var var; 5 | public VarExp(int p, Var v) {pos=p; var=v;} 6 | } 7 | -------------------------------------------------------------------------------- /testcases/test45.tig: -------------------------------------------------------------------------------- 1 | /* error: initializing nil expressions not constrained by record type */ 2 | let 3 | type rectype = {name:string, id:int} 4 | 5 | var a:= nil 6 | in 7 | a 8 | end 9 | -------------------------------------------------------------------------------- /chap4/Absyn/ArrayTy.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class ArrayTy extends Ty { 4 | public Symbol typ; 5 | public ArrayTy(int p, Symbol t) {pos=p; typ=t;} 6 | } 7 | -------------------------------------------------------------------------------- /chap4/Absyn/SeqExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class SeqExp extends Exp { 4 | public ExpList list; 5 | public SeqExp(int p, ExpList l) {pos=p; list=l;} 6 | } 7 | -------------------------------------------------------------------------------- /chap5/Types/STRING.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class STRING extends Type { 4 | public STRING(){} 5 | public boolean coerceTo(Type t) {return (t.actual() instanceof STRING);} 6 | } 7 | 8 | -------------------------------------------------------------------------------- /testcases/test32.tig: -------------------------------------------------------------------------------- 1 | /* error : initializing exp and array type differ */ 2 | 3 | let 4 | type arrayty = array of int 5 | 6 | var a := arrayty [10] of " " 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test49.tig: -------------------------------------------------------------------------------- 1 | /* error: syntax error, nil should not be preceded by type-id. */ 2 | let 3 | type rectype = {name:string, id:int} 4 | 5 | var a:= rectype nil 6 | in 7 | a 8 | end 9 | -------------------------------------------------------------------------------- /chap5/Types/Type.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public abstract class Type { 4 | public Type actual() {return this;} 5 | 6 | public boolean coerceTo(Type t) {return false;} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /chap6/Temp/TempList.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public class TempList { 4 | public Temp head; 5 | public TempList tail; 6 | public TempList(Temp h, TempList t) {head=h; tail=t;} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /chap6/Util/BoolList.java: -------------------------------------------------------------------------------- 1 | package Util; 2 | 3 | public class BoolList { 4 | public boolean head; 5 | public BoolList tail; 6 | public BoolList(boolean h, BoolList t) {head=h; tail=t;} 7 | } 8 | -------------------------------------------------------------------------------- /testcases/test22.tig: -------------------------------------------------------------------------------- 1 | /* error : field not in record type */ 2 | 3 | let 4 | type rectype = {name:string , id:int} 5 | var rec1 := rectype {name="Name", id=0} 6 | in 7 | rec1.nam := "asd" 8 | end 9 | -------------------------------------------------------------------------------- /chap4/Absyn/SimpleVar.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class SimpleVar extends Var { 4 | public Symbol name; 5 | public SimpleVar (int p, Symbol n) {pos=p; name=n;} 6 | } 7 | -------------------------------------------------------------------------------- /chap4/Absyn/StringExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class StringExp extends Exp { 4 | public String value; 5 | public StringExp(int p, String v) {pos=p; value=v;} 6 | } 7 | -------------------------------------------------------------------------------- /chap6/Temp/LabelList.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public class LabelList { 4 | public Label head; 5 | public LabelList tail; 6 | public LabelList(Label h, LabelList t) {head=h; tail=t;} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /chap7/Tree/ExpList.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | public class ExpList { 3 | public Exp head; 4 | public ExpList tail; 5 | public ExpList(Exp h, ExpList t) {head=h; tail=t;} 6 | } 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /chap7/Tree/StmList.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | public class StmList { 3 | public Stm head; 4 | public StmList tail; 5 | public StmList(Stm h, StmList t) {head=h; tail=t;} 6 | } 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /testcases/test44.tig: -------------------------------------------------------------------------------- 1 | /* valid nil initialization and assignment */ 2 | let 3 | 4 | type rectype = {name:string, id:int} 5 | var b:rectype := nil 6 | 7 | in 8 | 9 | b := nil 10 | 11 | end 12 | -------------------------------------------------------------------------------- /chap4/Absyn/DecList.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class DecList { 4 | public Dec head; 5 | public DecList tail; 6 | public DecList(Dec h, DecList t) {head=h; tail=t;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/ExpList.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class ExpList { 4 | public Exp head; 5 | public ExpList tail; 6 | public ExpList(Exp h, ExpList t) {head=h; tail=t;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/RecordTy.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class RecordTy extends Ty { 4 | public FieldList fields; 5 | public RecordTy(int p, FieldList f) {pos=p; fields=f;} 6 | } 7 | -------------------------------------------------------------------------------- /testcases/test16.tig: -------------------------------------------------------------------------------- 1 | /* error: mutually recursive types thet do not pass through record or array */ 2 | let 3 | 4 | type a=c 5 | type b=a 6 | type c=d 7 | type d=a 8 | 9 | in 10 | "" 11 | end 12 | -------------------------------------------------------------------------------- /chap10/Graph/NodeList.java: -------------------------------------------------------------------------------- 1 | package Graph; 2 | public class NodeList { 3 | public Node head; 4 | public NodeList tail; 5 | public NodeList(Node h, NodeList t) {head=h; tail=t;} 6 | } 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /chap4/Absyn/WhileExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class WhileExp extends Exp { 4 | public Exp test, body; 5 | public WhileExp(int p, Exp t, Exp b) {pos=p; test=t; body=b;} 6 | } 7 | -------------------------------------------------------------------------------- /testcases/test23.tig: -------------------------------------------------------------------------------- 1 | /* error : type mismatch */ 2 | 3 | let 4 | type rectype = {name:string , id:int} 5 | var rec1 := rectype {name="aname", id=0} 6 | in 7 | rec1.name := 3; 8 | rec1.id := "" 9 | end 10 | -------------------------------------------------------------------------------- /chap6/Temp/DefaultMap.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public class DefaultMap implements TempMap { 4 | public String tempMap(Temp.Temp t) { 5 | return t.toString(); 6 | } 7 | 8 | public DefaultMap() {} 9 | } 10 | -------------------------------------------------------------------------------- /chap9/Assem/InstrList.java: -------------------------------------------------------------------------------- 1 | package Assem; 2 | 3 | public class InstrList { 4 | public Instr head; 5 | public InstrList tail; 6 | public InstrList(Instr h, InstrList t) { 7 | head=h; tail=t; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /testcases/test2.tig: -------------------------------------------------------------------------------- 1 | /* arr1 is valid since expression 0 is int = myint */ 2 | let 3 | type myint = int 4 | type arrtype = array of myint 5 | 6 | var arr1:arrtype := arrtype [10] of 0 7 | in 8 | arr1 9 | end 10 | -------------------------------------------------------------------------------- /testcases/test29.tig: -------------------------------------------------------------------------------- 1 | /* error : different array types */ 2 | 3 | let 4 | type arrtype1 = array of int 5 | type arrtype2 = array of int 6 | 7 | var arr1: arrtype1 := arrtype2 [10] of 0 8 | in 9 | arr1 10 | end 11 | -------------------------------------------------------------------------------- /chap3/Parse/Main.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | public class Main { 4 | 5 | public static void main(String argv[]) { 6 | String filename = argv[0]; 7 | new Parse(filename); 8 | } 9 | 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /chap4/Absyn/AssignExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class AssignExp extends Exp { 4 | public Var var; 5 | public Exp exp; 6 | public AssignExp(int p, Var v, Exp e) {pos=p; var=v; exp=e;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Parse/Main.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | public class Main { 4 | 5 | public static void main(String argv[]) { 6 | String filename = argv[0]; 7 | new Parse(filename); 8 | } 9 | 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /chap8/Canon/StmListList.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | public class StmListList { 4 | public Tree.StmList head; 5 | public StmListList tail; 6 | public StmListList(Tree.StmList h, StmListList t) {head=h; tail=t;} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /chap9/Canon/StmListList.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | public class StmListList { 4 | public Tree.StmList head; 5 | public StmListList tail; 6 | public StmListList(Tree.StmList h, StmListList t) {head=h; tail=t;} 7 | } 8 | 9 | -------------------------------------------------------------------------------- /testcases/test3.tig: -------------------------------------------------------------------------------- 1 | /* a record type and a record variable */ 2 | let 3 | type rectype = {name:string, age:int} 4 | var rec1:rectype := rectype {name="Nobody", age=1000} 5 | in 6 | rec1.name := "Somebody"; 7 | rec1 8 | end 9 | -------------------------------------------------------------------------------- /testcases/test37.tig: -------------------------------------------------------------------------------- 1 | /* redeclaration of variable; this is legal, there are two different 2 | variables with the same name. The second one hides the first. */ 3 | let 4 | var a := 0 5 | var a := " " 6 | in 7 | 0 8 | end 9 | -------------------------------------------------------------------------------- /chap4/Absyn/LetExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class LetExp extends Exp { 4 | public DecList decs; 5 | public Exp body; 6 | public LetExp(int p, DecList d, Exp b) {pos=p; decs=d; body=b;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/FieldVar.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class FieldVar extends Var { 4 | public Var var; 5 | public Symbol field; 6 | public FieldVar(int p, Var v, Symbol f) {pos=p; var=v; field=f;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/CallExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class CallExp extends Exp { 4 | public Symbol func; 5 | public ExpList args; 6 | public CallExp(int p, Symbol f, ExpList a) {pos=p; func=f; args=a;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/ForExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class ForExp extends Exp { 4 | public VarDec var; 5 | public Exp hi, body; 6 | public ForExp(int p, VarDec v, Exp h, Exp b) {pos=p; var=v; hi=h; body=b;} 7 | } 8 | -------------------------------------------------------------------------------- /chap4/Absyn/SubscriptVar.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class SubscriptVar extends Var { 4 | public Var var; 5 | public Exp index; 6 | public SubscriptVar(int p, Var v, Exp i) {pos=p; var=v; index=i;} 7 | } 8 | -------------------------------------------------------------------------------- /testcases/test4.tig: -------------------------------------------------------------------------------- 1 | /* define a recursive function */ 2 | let 3 | 4 | /* calculate n! */ 5 | function nfactor(n: int): int = 6 | if n = 0 7 | then 1 8 | else n * nfactor(n-1) 9 | 10 | in 11 | nfactor(10) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /chap4/Absyn/ArrayExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class ArrayExp extends Exp { 4 | public Symbol typ; 5 | public Exp size, init; 6 | public ArrayExp(int p, Symbol t, Exp s, Exp i) {pos=p; typ=t; size=s; init=i;} 7 | } 8 | -------------------------------------------------------------------------------- /chap5/Types/ARRAY.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class ARRAY extends Type { 4 | public Type element; 5 | public ARRAY(Type e) {element = e;} 6 | public boolean coerceTo(Type t) { 7 | return this==t.actual(); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /chap6/Temp/Temp.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public class Temp { 4 | private static int count; 5 | private int num; 6 | public String toString() {return "t" + num;} 7 | public Temp() { 8 | num=count++; 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /chap4/Absyn/RecordExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class RecordExp extends Exp { 4 | public Symbol typ; 5 | public FieldExpList fields; 6 | public RecordExp(int p, Symbol t, FieldExpList f) {pos=p; typ=t;fields=f;} 7 | } 8 | -------------------------------------------------------------------------------- /testcases/test17.tig: -------------------------------------------------------------------------------- 1 | /* error: definition of recursive types is interrupted */ 2 | let 3 | /* define a tree */ 4 | type tree ={key: int, children: treelist} 5 | var d:int :=0 6 | type treelist = {hd: tree, tl: treelist} 7 | 8 | in 9 | d 10 | end 11 | -------------------------------------------------------------------------------- /testcases/test28.tig: -------------------------------------------------------------------------------- 1 | /* error : different record types */ 2 | 3 | let 4 | type rectype1 = {name:string , id:int} 5 | type rectype2 = {name:string , id:int} 6 | 7 | var rec1: rectype1 := rectype2 {name="Name", id=0} 8 | in 9 | rec1 10 | end 11 | -------------------------------------------------------------------------------- /chap5/Types/NIL.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class NIL extends Type { 4 | public NIL () {} 5 | public boolean coerceTo(Type t) { 6 | Type a = t.actual(); 7 | return (a instanceof RECORD) || (a instanceof NIL); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /chap7/Tree/TEMP.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | 3 | public class TEMP extends Exp { 4 | public Temp.Temp temp; 5 | public TEMP(Temp.Temp t) {temp=t;} 6 | public ExpList kids() {return null;} 7 | public Exp build(ExpList kids) {return this;} 8 | } 9 | 10 | -------------------------------------------------------------------------------- /testcases/test38.tig: -------------------------------------------------------------------------------- 1 | /* This is illegal, since there are two types with the same name 2 | in the same (consecutive) batch of mutually recursive types. 3 | See also test47 */ 4 | let 5 | type a = int 6 | type a = string 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /chap10/RegAlloc/MoveList.java: -------------------------------------------------------------------------------- 1 | package RegAlloc; 2 | 3 | public class MoveList { 4 | public Graph.Node src, dst; 5 | public MoveList tail; 6 | public MoveList(Graph.Node s, Graph.Node d, MoveList t) { 7 | src=s; dst=d; tail=t; 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /chap4/Absyn/TypeDec.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class TypeDec extends Dec { 4 | public Symbol name; 5 | public Ty ty; 6 | public TypeDec next; 7 | public TypeDec(int p, Symbol n, Ty t, TypeDec x) {pos=p; name=n; ty=t; next=x;} 8 | } 9 | -------------------------------------------------------------------------------- /testcases/test21.tig: -------------------------------------------------------------------------------- 1 | /* error : procedure returns value and procedure is used in arexpr */ 2 | let 3 | 4 | /* calculate n! */ 5 | function nfactor(n: int) = 6 | if n = 0 7 | then 1 8 | else n * nfactor(n-1) 9 | 10 | in 11 | nfactor(10) 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test6.tig: -------------------------------------------------------------------------------- 1 | /* define valid mutually recursive procedures */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string)= 5 | do_nothing2(a+1) 6 | 7 | function do_nothing2(d: int) = 8 | do_nothing1(d, "str") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test39.tig: -------------------------------------------------------------------------------- 1 | /* This is illegal, since there are two functions with the same name 2 | in the same (consecutive) batch of mutually recursive functions. 3 | See also test48 */ 4 | let 5 | function g(a:int):int = a 6 | function g(a:int):int = a 7 | in 8 | 0 9 | end 10 | -------------------------------------------------------------------------------- /chap7/Tree/CONST.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class CONST extends Exp { 5 | public int value; 6 | public CONST(int v) {value=v;} 7 | public ExpList kids() {return null;} 8 | public Exp build(ExpList kids) {return this;} 9 | } 10 | 11 | -------------------------------------------------------------------------------- /chap7/Tree/NAME.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class NAME extends Exp { 5 | public Label label; 6 | public NAME(Label l) {label=l;} 7 | public ExpList kids() {return null;} 8 | public Exp build(ExpList kids) {return this;} 9 | } 10 | 11 | -------------------------------------------------------------------------------- /testcases/test14.tig: -------------------------------------------------------------------------------- 1 | /* error : compare rec with array */ 2 | 3 | let 4 | 5 | type arrtype = array of int 6 | type rectype = {name:string, id: int} 7 | 8 | var rec := rectype {name="aname", id=0} 9 | var arr := arrtype [3] of 0 10 | 11 | in 12 | if rec <> arr then 3 else 4 13 | end 14 | -------------------------------------------------------------------------------- /testcases/test7.tig: -------------------------------------------------------------------------------- 1 | /* define valid mutually recursive functions */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | function do_nothing2(d: int):string = 8 | (do_nothing1(d, "str");" ") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /chap7/Tree/LABEL.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class LABEL extends Stm { 5 | public Label label; 6 | public LABEL(Label l) {label=l;} 7 | public ExpList kids() {return null;} 8 | public Stm build(ExpList kids) { 9 | return this; 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /chap4/Absyn/FieldExpList.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class FieldExpList extends Absyn { 4 | public Symbol name; 5 | public Exp init; 6 | public FieldExpList tail; 7 | public FieldExpList(int p, Symbol n, Exp i, FieldExpList t) {pos=p; 8 | name=n; init=i; tail=t; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /chap4/Absyn/VarDec.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class VarDec extends Dec { 4 | public Symbol name; 5 | public boolean escape = true; 6 | public NameTy typ; /* optional */ 7 | public Exp init; 8 | public VarDec(int p, Symbol n, NameTy t, Exp i) {pos=p; name=n; typ=t; init=i;} 9 | } 10 | -------------------------------------------------------------------------------- /chap7/Tree/MEM.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class MEM extends Exp { 5 | public Exp exp; 6 | public MEM(Exp e) {exp=e;} 7 | public ExpList kids() {return new ExpList(exp,null);} 8 | public Exp build(ExpList kids) { 9 | return new MEM(kids.head); 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /chap7/Tree/EXP.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class EXP extends Stm { 5 | public Exp exp; 6 | public EXP(Exp e) {exp=e;} 7 | public ExpList kids() {return new ExpList(exp,null);} 8 | public Stm build(ExpList kids) { 9 | return new EXP(kids.head); 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /chap4/Absyn/FieldList.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class FieldList extends Absyn { 4 | public Symbol name; 5 | public Symbol typ; 6 | public FieldList tail; 7 | public boolean escape = true; 8 | public FieldList(int p, Symbol n, Symbol t, FieldList x) {pos=p; name=n; typ=t; tail=x;} 9 | } 10 | -------------------------------------------------------------------------------- /testcases/test18.tig: -------------------------------------------------------------------------------- 1 | /* error : definition of recursive functions is interrupted */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | var d:=0 8 | 9 | function do_nothing2(d: int):string = 10 | (do_nothing1(d, "str");" ") 11 | 12 | in 13 | do_nothing1(0, "str2") 14 | end 15 | 16 | -------------------------------------------------------------------------------- /testcases/test19.tig: -------------------------------------------------------------------------------- 1 | /* error : second function uses variables local to the first one, undeclared variable */ 2 | let 3 | 4 | function do_nothing1(a: int, b: string):int= 5 | (do_nothing2(a+1);0) 6 | 7 | function do_nothing2(d: int):string = 8 | (do_nothing1(a, "str");" ") 9 | 10 | in 11 | do_nothing1(0, "str2") 12 | end 13 | 14 | -------------------------------------------------------------------------------- /testcases/test47.tig: -------------------------------------------------------------------------------- 1 | /* This is legal. The second type "a" simply hides the first one. 2 | Because of the intervening variable declaration, the two "a" types 3 | are not in the same batch of mutually recursive types. 4 | See also test38 */ 5 | let 6 | type a = int 7 | var b := 4 8 | type a = string 9 | in 10 | 0 11 | end 12 | -------------------------------------------------------------------------------- /testcases/test5.tig: -------------------------------------------------------------------------------- 1 | /* define valid recursive types */ 2 | let 3 | /* define a list */ 4 | type intlist = {hd: int, tl: intlist} 5 | 6 | /* define a tree */ 7 | type tree ={key: int, children: treelist} 8 | type treelist = {hd: tree, tl: treelist} 9 | 10 | var lis:intlist := intlist { hd=0, tl= nil } 11 | 12 | in 13 | lis 14 | end 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Modern Compiler Implementation in Java 2 | ====================================== 3 | 4 | [Modern Compiler Implementation in Java](http://www.cs.princeton.edu/~appel/modern/java/) by [Andrew W. Appel](http://www.cs.princeton.edu/~appel) has been sitting on my shelf long enough. It's time I work through it, you know, in my infinite spare time. 5 | -------------------------------------------------------------------------------- /chap4/Absyn/OpExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class OpExp extends Exp { 4 | public Exp left, right; 5 | public int oper; 6 | public OpExp(int p, Exp l, int o, Exp r) {pos=p; left=l; oper=o; right=r;} 7 | public final static int PLUS=0, MINUS=1, MUL=2, DIV=3, 8 | EQ=4, NE=5, LT=6, LE=7, GT=8, GE=9; 9 | } 10 | -------------------------------------------------------------------------------- /chap10/RegAlloc/InterferenceGraph.java: -------------------------------------------------------------------------------- 1 | package RegAlloc; 2 | import Graph.Node; 3 | import Graph.Graph; 4 | 5 | abstract public class InterferenceGraph extends Graph { 6 | abstract public Node tnode(Temp.Temp temp); 7 | abstract public Temp.Temp gtemp(Node node); 8 | abstract public MoveList moves(); 9 | public int spillCost(Node node) {return 1;} 10 | } 11 | -------------------------------------------------------------------------------- /chap9/Assem/LABEL.java: -------------------------------------------------------------------------------- 1 | package Assem; 2 | 3 | public class LABEL extends Instr { 4 | public Temp.Label label; 5 | 6 | public LABEL(String a, Temp.Label l) { 7 | assem=a; label=l; 8 | } 9 | 10 | public Temp.TempList use() {return null;} 11 | public Temp.TempList def() {return null;} 12 | public Targets jumps() {return null;} 13 | 14 | } 15 | -------------------------------------------------------------------------------- /chap6/Temp/CombineMap.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | 3 | public class CombineMap implements TempMap { 4 | TempMap tmap1, tmap2; 5 | public String tempMap(Temp.Temp t) { 6 | String s = tmap1.tempMap(t); 7 | if (s!=null) return s; 8 | return tmap2.tempMap(t); 9 | } 10 | 11 | public CombineMap(TempMap t1, TempMap t2) { 12 | tmap1=t1; tmap2=t2; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /chap7/Tree/SEQ.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class SEQ extends Stm { 5 | public Stm left, right; 6 | public SEQ(Stm l, Stm r) { left=l; right=r; } 7 | public ExpList kids() {throw new Error("kids() not applicable to SEQ");} 8 | public Stm build(ExpList kids) {throw new Error("build() not applicable to SEQ");} 9 | } 10 | 11 | -------------------------------------------------------------------------------- /testcases/test48.tig: -------------------------------------------------------------------------------- 1 | /* This is legal. The second function "g" simply hides the first one. 2 | Because of the intervening variable declaration, the two "g" functions 3 | are not in the same batch of mutually recursive functions. 4 | See also test39 */ 5 | let 6 | function g(a:int):int = a 7 | type t = int 8 | function g(a:int):int = a 9 | in 10 | 0 11 | end 12 | -------------------------------------------------------------------------------- /chap4/Absyn/IfExp.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class IfExp extends Exp { 4 | public Exp test; 5 | public Exp thenclause; 6 | public Exp elseclause; /* optional */ 7 | public IfExp(int p, Exp x, Exp y) {pos=p; test=x; thenclause=y; elseclause=null;} 8 | public IfExp(int p, Exp x, Exp y, Exp z) {pos=p; test=x; thenclause=y; elseclause=z;} 9 | } 10 | -------------------------------------------------------------------------------- /chap7/Tree/ESEQ.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class ESEQ extends Exp { 5 | public Stm stm; 6 | public Exp exp; 7 | public ESEQ(Stm s, Exp e) {stm=s; exp=e;} 8 | public ExpList kids() {throw new Error("kids() not applicable to ESEQ");} 9 | public Exp build(ExpList kids) {throw new Error("build() not applicable to ESEQ");} 10 | } 11 | 12 | -------------------------------------------------------------------------------- /chap5/Types/RECORD.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class RECORD extends Type { 4 | public Symbol.Symbol fieldName; 5 | public Type fieldType; 6 | public RECORD tail; 7 | public RECORD(Symbol.Symbol n, Type t, RECORD x) { 8 | fieldName=n; fieldType=t; tail=x; 9 | } 10 | public boolean coerceTo(Type t) { 11 | return this==t.actual(); 12 | } 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /chap7/Tree/CALL.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class CALL extends Exp { 5 | public Exp func; 6 | public ExpList args; 7 | public CALL(Exp f, ExpList a) {func=f; args=a;} 8 | public ExpList kids() {return new ExpList(func,args);} 9 | public Exp build(ExpList kids) { 10 | return new CALL(kids.head,kids.tail); 11 | } 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /chap2/makefile: -------------------------------------------------------------------------------- 1 | JFLAGS=-g 2 | 3 | 4 | Parse/Main.class: Parse/*.java Parse/Yylex.java 5 | javac ${JFLAGS} Parse/*.java 6 | 7 | Parse/Yylex.java: Parse/Tiger.lex 8 | cd Parse; java JLex.Main Tiger.lex; mv Tiger.lex.java Yylex.java 9 | 10 | ErrorMsg/ErrorMsg.class: ErrorMsg/*.java 11 | javac ${JFLAGS} ErrorMsg/*.java 12 | 13 | clean: 14 | rm Parse/*.class ErrorMsg/*.class Parse/Yylex.java 15 | 16 | 17 | -------------------------------------------------------------------------------- /chap4/Absyn/FunctionDec.java: -------------------------------------------------------------------------------- 1 | package Absyn; 2 | import Symbol.Symbol; 3 | public class FunctionDec extends Dec { 4 | public Symbol name; 5 | public FieldList params; 6 | public NameTy result; /* optional */ 7 | public Exp body; 8 | public FunctionDec next; 9 | public FunctionDec(int p, Symbol n, FieldList a, NameTy r, Exp b, FunctionDec x) 10 | {pos=p; name=n; params=a; result=r; body=b; next=x;} 11 | } 12 | -------------------------------------------------------------------------------- /chap9/Assem/MOVE.java: -------------------------------------------------------------------------------- 1 | package Assem; 2 | 3 | public class MOVE extends Instr { 4 | public Temp.Temp dst; 5 | public Temp.Temp src; 6 | 7 | public MOVE(String a, Temp.Temp d, Temp.Temp s) { 8 | assem=a; dst=d; src=s; 9 | } 10 | public Temp.TempList use() {return new Temp.TempList(src,null);} 11 | public Temp.TempList def() {return new Temp.TempList(dst,null);} 12 | public Targets jumps() {return null;} 13 | 14 | } 15 | -------------------------------------------------------------------------------- /chap3/makefile: -------------------------------------------------------------------------------- 1 | JFLAGS=-g 2 | 3 | 4 | Parse/Main.class: Parse/*.java Parse/Grm.java Parse/Yylex.java 5 | javac ${JFLAGS} Parse/*.java 6 | 7 | Parse/Grm.java: Parse/Grm.cup 8 | cd Parse; java java_cup.Main -parser Grm -expect 3 -dump_grammar -dump_states Grm.out 2>Grm.err 9 | 10 | Parse/Yylex.java: Parse/Tiger.lex 11 | cd Parse; java JLex.Main Tiger.lex; mv Tiger.lex.java Yylex.java 12 | 13 | ErrorMsg/ErrorMsg.class: ErrorMsg/*.java 14 | javac ${JFLAGS} ErrorMsg/*.java 15 | 16 | 17 | -------------------------------------------------------------------------------- /chap1/prog.java: -------------------------------------------------------------------------------- 1 | class prog { 2 | static Stm prog = 3 | new CompoundStm(new AssignStm("a",new OpExp(new NumExp(5), OpExp.Plus, 4 | new NumExp(3))), 5 | new CompoundStm(new AssignStm("b", 6 | new EseqExp(new PrintStm(new PairExpList(new IdExp("a"), 7 | new LastExpList(new OpExp(new IdExp("a"), OpExp.Minus, 8 | new NumExp(1))))), 9 | new OpExp(new NumExp(10), OpExp.Times, new IdExp("a")))), 10 | new PrintStm(new LastExpList(new IdExp("b"))))); 11 | } 12 | -------------------------------------------------------------------------------- /chap7/Tree/JUMP.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class JUMP extends Stm { 5 | public Exp exp; 6 | public Temp.LabelList targets; 7 | public JUMP(Exp e, Temp.LabelList t) {exp=e; targets=t;} 8 | public JUMP(Temp.Label target) { 9 | this(new NAME(target), new Temp.LabelList(target,null)); 10 | } 11 | public ExpList kids() {return new ExpList(exp,null);} 12 | public Stm build(ExpList kids) { 13 | return new JUMP(kids.head,targets); 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /chap4/Parse/Token.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | class Token extends java_cup.runtime.token { 4 | int left,right; 5 | Token(int l, int r, int kind) { 6 | super(kind); 7 | left=l; right=r; 8 | } 9 | } 10 | 11 | class StrToken extends Token { 12 | String val; 13 | StrToken(int l, int r, int kind, String v) { 14 | super(l,r,kind); 15 | val=v; 16 | } 17 | } 18 | 19 | class IntToken extends Token { 20 | int val; 21 | IntToken(int l, int r, int kind, int v) { 22 | super(l,r,kind); 23 | val=v; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /chap7/Tree/BINOP.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class BINOP extends Exp { 5 | public int binop; 6 | public Exp left, right; 7 | public BINOP(int b, Exp l, Exp r) { 8 | binop=b; left=l; right=r; 9 | } 10 | public final static int PLUS=0, MINUS=1, MUL=2, DIV=3, 11 | AND=4,OR=5,LSHIFT=6,RSHIFT=7,ARSHIFT=8,XOR=9; 12 | public ExpList kids() {return new ExpList(left, new ExpList(right,null));} 13 | public Exp build(ExpList kids) { 14 | return new BINOP(binop,kids.head,kids.tail.head); 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /chap7/Tree/MOVE.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | import Temp.Temp; 3 | import Temp.Label; 4 | public class MOVE extends Stm { 5 | public Exp dst, src; 6 | public MOVE(Exp d, Exp s) {dst=d; src=s;} 7 | public ExpList kids() { 8 | if (dst instanceof MEM) 9 | return new ExpList(((MEM)dst).exp, new ExpList(src,null)); 10 | else return new ExpList(src,null); 11 | } 12 | public Stm build(ExpList kids) { 13 | if (dst instanceof MEM) 14 | return new MOVE(new MEM(kids.head), kids.tail.head); 15 | else return new MOVE(dst, kids.head); 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /chap9/Assem/OPER.java: -------------------------------------------------------------------------------- 1 | package Assem; 2 | 3 | public class OPER extends Instr { 4 | public Temp.TempList dst; 5 | public Temp.TempList src; 6 | public Targets jump; 7 | 8 | public OPER(String a, Temp.TempList d, Temp.TempList s, Temp.LabelList j) { 9 | assem=a; dst=d; src=s; jump=new Targets(j); 10 | } 11 | public OPER(String a, Temp.TempList d, Temp.TempList s) { 12 | assem=a; dst=d; src=s; jump=null; 13 | } 14 | 15 | public Temp.TempList use() {return src;} 16 | public Temp.TempList def() {return dst;} 17 | public Targets jumps() {return jump;} 18 | 19 | } 20 | -------------------------------------------------------------------------------- /chap4/Symbol/Symbol.java: -------------------------------------------------------------------------------- 1 | package Symbol; 2 | public class Symbol { 3 | private String name; 4 | private Symbol(String n) { 5 | name=n; 6 | } 7 | private static java.util.Dictionary dict = new java.util.Hashtable(); 8 | 9 | public String toString() { 10 | return name; 11 | } 12 | 13 | /** 14 | * Make return the unique symbol associated with a string. 15 | * Repeated calls to symbol("abc") will return the same Symbol. 16 | */ 17 | 18 | public static Symbol symbol(String n) { 19 | String u = n.intern(); 20 | Symbol s = (Symbol)dict.get(u); 21 | if (s==null) { 22 | s = new Symbol(u); 23 | dict.put(u,s); 24 | } 25 | return s; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /chap5/Types/NAME.java: -------------------------------------------------------------------------------- 1 | package Types; 2 | 3 | public class NAME extends Type { 4 | public Symbol.Symbol name; 5 | private Type binding; 6 | public NAME(Symbol.Symbol n) {name=n;} 7 | public boolean isLoop() { 8 | Type b = binding; 9 | boolean any; 10 | binding=null; 11 | if (b==null) any=true; 12 | else if (b instanceof NAME) 13 | any=((NAME)b).isLoop(); 14 | else any=false; 15 | binding=b; 16 | return any; 17 | } 18 | 19 | public Type actual() {return binding.actual();} 20 | 21 | public boolean coerceTo(Type t) { 22 | return this.actual().coerceTo(t); 23 | } 24 | public void bind(Type t) {binding = t;} 25 | } 26 | -------------------------------------------------------------------------------- /chap3/Parse/Parse.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | public class Parse { 4 | 5 | public ErrorMsg.ErrorMsg errorMsg; 6 | 7 | public Parse(String filename) { 8 | errorMsg = new ErrorMsg.ErrorMsg(filename); 9 | java.io.InputStream inp; 10 | try {inp=new java.io.FileInputStream(filename); 11 | } catch (java.io.FileNotFoundException e) { 12 | throw new Error("File not found: " + filename); 13 | } 14 | Grm parser = new Grm(new Yylex(inp,errorMsg), errorMsg); 15 | 16 | try { 17 | parser./*debug_*/parse(); 18 | } catch (Throwable e) { 19 | e.printStackTrace(); 20 | throw new Error(e.toString()); 21 | } 22 | finally { 23 | try {inp.close();} catch (java.io.IOException e) {} 24 | } 25 | } 26 | } 27 | 28 | 29 | -------------------------------------------------------------------------------- /testcases/test42.tig: -------------------------------------------------------------------------------- 1 | /* correct declarations */ 2 | let 3 | 4 | type arrtype1 = array of int 5 | type rectype1 = {name:string, address:string, id: int , age: int} 6 | type arrtype2 = array of rectype1 7 | type rectype2 = {name : string, dates: arrtype1} 8 | 9 | type arrtype3 = array of string 10 | 11 | var arr1 := arrtype1 [10] of 0 12 | var arr2 := arrtype2 [5] of rectype1 {name="aname", address="somewhere", id=0, age=0} 13 | var arr3:arrtype3 := arrtype3 [100] of "" 14 | 15 | var rec1 := rectype1 {name="Kapoios", address="Kapou", id=02432, age=44} 16 | var rec2 := rectype2 {name="Allos", dates= arrtype1 [3] of 1900} 17 | 18 | in 19 | 20 | arr1[0] := 1; 21 | arr1[9] := 3; 22 | arr2[3].name := "kati"; 23 | arr2[1].age := 23; 24 | arr3[34] := "sfd"; 25 | 26 | rec1.name := "sdf"; 27 | rec2.dates[0] := 2323; 28 | rec2.dates[2] := 2323 29 | 30 | end 31 | -------------------------------------------------------------------------------- /chap4/Parse/Parse.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | public class Parse { 4 | 5 | public ErrorMsg.ErrorMsg errorMsg; 6 | public Absyn.Exp absyn; 7 | 8 | public Parse(String filename) { 9 | errorMsg = new ErrorMsg.ErrorMsg(filename); 10 | {java.io.InputStream inp; 11 | try {inp=new java.io.FileInputStream(filename); 12 | } catch (java.io.FileNotFoundException e) { 13 | throw new Error("File not found: " + filename); 14 | } 15 | Grm parser = new Grm(new Yylex(inp,errorMsg), errorMsg); 16 | /* open input files, etc. here */ 17 | 18 | try { 19 | parser./*debug_*/parse(); 20 | } catch (Throwable e) { 21 | e.printStackTrace(); 22 | throw new Error(e.toString()); 23 | } 24 | finally { 25 | try {inp.close();} catch (java.io.IOException e) {} 26 | } 27 | absyn=parser.parseResult; 28 | } } } 29 | 30 | -------------------------------------------------------------------------------- /chap2/Parse/Tiger.lex: -------------------------------------------------------------------------------- 1 | package Parse; 2 | import ErrorMsg.ErrorMsg; 3 | 4 | %% 5 | 6 | %implements Lexer 7 | %function nextToken 8 | %type java_cup.runtime.Symbol 9 | %char 10 | 11 | %{ 12 | private void newline() { 13 | errorMsg.newline(yychar); 14 | } 15 | 16 | private void err(int pos, String s) { 17 | errorMsg.error(pos,s); 18 | } 19 | 20 | private void err(String s) { 21 | err(yychar,s); 22 | } 23 | 24 | private java_cup.runtime.Symbol tok(int kind, Object value) { 25 | return new java_cup.runtime.Symbol(kind, yychar, yychar+yylength(), value); 26 | } 27 | 28 | private ErrorMsg.ErrorMsg errorMsg; 29 | 30 | Yylex(java.io.InputStream s, ErrorMsg.ErrorMsg e) { 31 | this(s); 32 | errorMsg=e; 33 | } 34 | 35 | %} 36 | 37 | %eofval{ 38 | { 39 | return tok(sym.EOF, null); 40 | } 41 | %eofval} 42 | 43 | 44 | %% 45 | " " {} 46 | \n {newline();} 47 | "," {return tok(sym.COMMA, null);} 48 | 49 | 50 | -------------------------------------------------------------------------------- /chap6/Temp/Label.java: -------------------------------------------------------------------------------- 1 | package Temp; 2 | import Symbol.Symbol; 3 | 4 | /** 5 | * A Label represents an address in assembly language. 6 | */ 7 | 8 | public class Label { 9 | private String name; 10 | private static int count; 11 | 12 | /** 13 | * a printable representation of the label, for use in assembly 14 | * language output. 15 | */ 16 | public String toString() {return name;} 17 | 18 | /** 19 | * Makes a new label that prints as "name". 20 | * Warning: avoid repeated calls to new Label(s) with 21 | * the same name s. 22 | */ 23 | public Label(String n) { 24 | name=n; 25 | } 26 | 27 | /** 28 | * Makes a new label with an arbitrary name. 29 | */ 30 | public Label() { 31 | this("L" + count++); 32 | } 33 | 34 | /** 35 | * Makes a new label whose name is the same as a symbol. 36 | */ 37 | public Label(Symbol s) { 38 | this(s.toString()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /testcases/queens.tig: -------------------------------------------------------------------------------- 1 | /* A program to solve the 8-queens problem */ 2 | 3 | let 4 | var N := 8 5 | 6 | type intArray = array of int 7 | 8 | var row := intArray [ N ] of 0 9 | var col := intArray [ N ] of 0 10 | var diag1 := intArray [N+N-1] of 0 11 | var diag2 := intArray [N+N-1] of 0 12 | 13 | function printboard() = 14 | (for i := 0 to N-1 15 | do (for j := 0 to N-1 16 | do print(if col[i]=j then " O" else " ."); 17 | print("\n")); 18 | print("\n")) 19 | 20 | function try(c:int) = 21 | ( /* for i:= 0 to c do print("."); print("\n"); flush();*/ 22 | if c=N 23 | then printboard() 24 | else for r := 0 to N-1 25 | do if row[r]=0 & diag1[r+c]=0 & diag2[r+7-c]=0 26 | then (row[r]:=1; diag1[r+c]:=1; diag2[r+7-c]:=1; 27 | col[c]:=r; 28 | try(c+1); 29 | row[r]:=0; diag1[r+c]:=0; diag2[r+7-c]:=0) 30 | 31 | ) 32 | in try(0) 33 | end 34 | -------------------------------------------------------------------------------- /chap2/ErrorMsg/ErrorMsg.java: -------------------------------------------------------------------------------- 1 | package ErrorMsg; 2 | 3 | public class ErrorMsg { 4 | private LineList linePos = new LineList(-1,null); 5 | private int lineNum=1; 6 | private String filename; 7 | public boolean anyErrors; 8 | 9 | public ErrorMsg(String f) { 10 | filename=f; 11 | } 12 | 13 | public void newline(int pos) { 14 | lineNum++; 15 | linePos = new LineList(pos,linePos); 16 | } 17 | public void error(int pos, String msg) { 18 | int n = lineNum; 19 | LineList p = linePos; 20 | String sayPos="0.0"; 21 | 22 | anyErrors=true; 23 | 24 | while (p!=null) { 25 | if (p.head=ord("0") & ord(buffer)<=ord("9") 10 | function skipto() = 11 | while buffer=" " | buffer="\n" 12 | do buffer := getchar() 13 | in skipto(); 14 | any.any := isdigit(buffer); 15 | while isdigit(buffer) 16 | do (i := i*10+ord(buffer)-ord("0"); buffer := getchar()); 17 | i 18 | end 19 | 20 | type list = {first: int, rest: list} 21 | 22 | function readlist() : list = 23 | let var any := any{any=0} 24 | var i := readint(any) 25 | in if any.any 26 | then list{first=i,rest=readlist()} 27 | else nil 28 | end 29 | 30 | function merge(a: list, b: list) : list = 31 | if a=nil then b 32 | else if b=nil then a 33 | else if a.first < b.first 34 | then list{first=a.first,rest=merge(a.rest,b)} 35 | else list{first=b.first,rest=merge(a,b.rest)} 36 | 37 | function printint(i: int) = 38 | let function f(i:int) = if i>0 39 | then (f(i/10); print(chr(i-i/10*10+ord("0")))) 40 | in if i<0 then (print("-"); f(-i)) 41 | else if i>0 then f(i) 42 | else print("0") 43 | end 44 | 45 | function printlist(l: list) = 46 | if l=nil then print("\n") 47 | else (printint(l.first); print(" "); printlist(l.rest)) 48 | 49 | var list1 := readlist() 50 | var list2 := (buffer:=getchar(); readlist()) 51 | 52 | 53 | /* BODY OF MAIN PROGRAM */ 54 | in printlist(merge(list1,list2)) 55 | end 56 | 57 | -------------------------------------------------------------------------------- /chap10/Graph/Graph.java: -------------------------------------------------------------------------------- 1 | package Graph; 2 | 3 | public class Graph { 4 | 5 | int nodecount=0; 6 | NodeList mynodes, mylast; 7 | public NodeList nodes() { return mynodes;} 8 | 9 | public Node newNode() { 10 | return new Node(this); 11 | } 12 | 13 | void check(Node n) { 14 | if (n.mygraph != this) 15 | throw new Error("Graph.addEdge using nodes from the wrong graph"); 16 | } 17 | 18 | static boolean inList(Node a, NodeList l) { 19 | for(NodeList p=l; p!=null; p=p.tail) 20 | if (p.head==a) return true; 21 | return false; 22 | } 23 | 24 | public void addEdge(Node from, Node to) { 25 | check(from); check(to); 26 | if (from.goesTo(to)) return; 27 | to.preds=new NodeList(from, to.preds); 28 | from.succs=new NodeList(to, from.succs); 29 | } 30 | 31 | NodeList delete(Node a, NodeList l) { 32 | if (l==null) throw new Error("Graph.rmEdge: edge nonexistent"); 33 | else if (a==l.head) return l.tail; 34 | else return new NodeList(l.head, delete(a, l.tail)); 35 | } 36 | 37 | public void rmEdge(Node from, Node to) { 38 | to.preds=delete(from,to.preds); 39 | from.succs=delete(to,from.succs); 40 | } 41 | 42 | /** 43 | * Print a human-readable dump for debugging. 44 | */ 45 | public void show(java.io.PrintStream out) { 46 | for (NodeList p=nodes(); p!=null; p=p.tail) { 47 | Node n = p.head; 48 | out.print(n.toString()); 49 | out.print(": "); 50 | for(NodeList q=n.succ(); q!=null; q=q.tail) { 51 | out.print(q.head.toString()); 52 | out.print(" "); 53 | } 54 | out.println(); 55 | } 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /chap4/Symbol/Table.java: -------------------------------------------------------------------------------- 1 | package Symbol; 2 | 3 | class Binder { 4 | Object value; 5 | Symbol prevtop; 6 | Binder tail; 7 | Binder(Object v, Symbol p, Binder t) { 8 | value=v; prevtop=p; tail=t; 9 | } 10 | } 11 | 12 | /** 13 | * The Table class is similar to java.util.Dictionary, except that 14 | * each key must be a Symbol and there is a scope mechanism. 15 | */ 16 | 17 | 18 | public class Table { 19 | 20 | private java.util.Dictionary dict = new java.util.Hashtable(); 21 | private Symbol top; 22 | private Binder marks; 23 | 24 | public Table(){} 25 | 26 | /** 27 | * Gets the object associated with the specified symbol in the Table. 28 | */ 29 | public Object get(Symbol key) { 30 | Binder e = (Binder)dict.get(key); 31 | if (e==null) return null; 32 | else return e.value; 33 | } 34 | 35 | /** 36 | * Puts the specified value into the Table, bound to the specified Symbol. 37 | */ 38 | public void put(Symbol key, Object value) { 39 | dict.put(key, new Binder(value, top, (Binder)dict.get(key))); 40 | top = key; 41 | } 42 | 43 | /** 44 | * Remembers the current state of the Table. 45 | */ 46 | public void beginScope() {marks = new Binder(null,top,marks); top=null;} 47 | 48 | /** 49 | * Restores the table to what it was at the most recent beginScope 50 | * that has not already been ended. 51 | */ 52 | public void endScope() { 53 | while (top!=null) { 54 | Binder e = (Binder)dict.get(top); 55 | if (e.tail!=null) dict.put(top,e.tail); 56 | else dict.remove(top); 57 | top = e.prevtop; 58 | } 59 | top=marks.prevtop; 60 | marks=marks.tail; 61 | } 62 | 63 | /** 64 | * Returns an enumeration of the Table's symbols. 65 | */ 66 | public java.util.Enumeration keys() {return dict.keys();} 67 | } 68 | 69 | -------------------------------------------------------------------------------- /chap10/FlowGraph/FlowGraph.java: -------------------------------------------------------------------------------- 1 | package FlowGraph; 2 | import Temp.TempList; 3 | import Temp.Temp; 4 | import Graph.NodeList; 5 | import Graph.Node; 6 | 7 | /** 8 | * A control flow graph is a directed graph in which each edge 9 | * indicates a possible flow of control. Also, each node in 10 | * the graph defines a set of temporaries; each node uses a set of 11 | * temporaries; and each node is, or is not, a move 12 | * instruction. 13 | * 14 | * @see AssemFlowGraph 15 | */ 16 | 17 | public abstract class FlowGraph extends Graph.Graph { 18 | /** 19 | * The set of temporaries defined by this instruction or block 20 | */ 21 | public abstract TempList def(Node node); 22 | 23 | /** 24 | * The set of temporaries used by this instruction or block 25 | */ 26 | public abstract TempList use(Node node); 27 | 28 | /** 29 | * True if this node represents a move instruction, 30 | * i.e. one that can be deleted if def=use. 31 | */ 32 | public abstract boolean isMove(Node node); 33 | 34 | /** 35 | * Print a human-readable dump for debugging. 36 | */ 37 | public void show(java.io.PrintStream out) { 38 | for (NodeList p=nodes(); p!=null; p=p.tail) { 39 | Node n = p.head; 40 | out.print(n.toString()); 41 | out.print(": "); 42 | for(TempList q=def(n); q!=null; q=q.tail) { 43 | out.print(q.head.toString()); 44 | out.print(" "); 45 | } 46 | out.print(isMove(n) ? "<= " : "<- "); 47 | for(TempList q=use(n); q!=null; q=q.tail) { 48 | out.print(q.head.toString()); 49 | out.print(" "); 50 | } 51 | out.print("; goto "); 52 | for(NodeList q=n.succ(); q!=null; q=q.tail) { 53 | out.print(q.head.toString()); 54 | out.print(" "); 55 | } 56 | out.println(); 57 | } 58 | } 59 | 60 | } 61 | 62 | -------------------------------------------------------------------------------- /chap2/Parse/sym.java: -------------------------------------------------------------------------------- 1 | 2 | //---------------------------------------------------- 3 | // The following code was generated by CUP v0.10a 4 | // Wed Jul 24 21:44:00 EDT 1996 5 | //---------------------------------------------------- 6 | 7 | package Parse; 8 | 9 | /** Cup generated class containing symbol constants. */ 10 | public class sym { 11 | /* terminals */ 12 | static final int FUNCTION = 42; 13 | static final int EOF = 0; 14 | static final int INT = 4; 15 | static final int GT = 23; 16 | static final int DIVIDE = 18; 17 | static final int COLON = 6; 18 | static final int ELSE = 31; 19 | static final int OR = 26; 20 | static final int NIL = 41; 21 | static final int DO = 35; 22 | static final int GE = 24; 23 | static final int error = 1; 24 | static final int LT = 21; 25 | static final int OF = 39; 26 | static final int MINUS = 16; 27 | static final int ARRAY = 28; 28 | static final int TYPE = 44; 29 | static final int FOR = 33; 30 | static final int TO = 34; 31 | static final int TIMES = 17; 32 | static final int COMMA = 5; 33 | static final int LE = 22; 34 | static final int IN = 37; 35 | static final int END = 38; 36 | static final int ASSIGN = 27; 37 | static final int STRING = 3; 38 | static final int DOT = 14; 39 | static final int LPAREN = 8; 40 | static final int RPAREN = 9; 41 | static final int IF = 29; 42 | static final int SEMICOLON = 7; 43 | static final int ID = 2; 44 | static final int WHILE = 32; 45 | static final int LBRACK = 10; 46 | static final int RBRACK = 11; 47 | static final int NEQ = 20; 48 | static final int VAR = 43; 49 | static final int BREAK = 40; 50 | static final int AND = 25; 51 | static final int PLUS = 15; 52 | static final int LBRACE = 12; 53 | static final int RBRACE = 13; 54 | static final int LET = 36; 55 | static final int THEN = 30; 56 | static final int EQ = 19; 57 | }; 58 | 59 | -------------------------------------------------------------------------------- /chap1/exer1_1.java: -------------------------------------------------------------------------------- 1 | class Tree { 2 | Tree left; 3 | String key; 4 | Object value; 5 | Tree right; 6 | 7 | Tree(Tree l, String k, Object v, Tree r) { 8 | left = l; 9 | key = k; 10 | value = v; 11 | right = r; 12 | } 13 | 14 | boolean member(String k) { 15 | int comp = k.compareTo(key); 16 | if (comp < 0) return (left != null) ? left.member(k) : false; 17 | else if (comp > 0) return (right != null) ? right.member(k) : false; 18 | else return true; 19 | } 20 | 21 | Tree insert(String key, Object binding) { 22 | if (key.compareTo(this.key) < 0) { 23 | return new Tree(left.insert(key, binding), this.key, value, right); 24 | } else if (key.compareTo(this.key) > 0) { 25 | return new Tree(left, this.key, value, right.insert(key, binding)); 26 | } else { 27 | return new Tree(left, key, binding, right); 28 | } 29 | } 30 | 31 | public String toString() { 32 | String l = (left != null) ? left.toString() : ""; 33 | String r = (right != null) ? right.toString() : ""; 34 | return "{key: "+ key+", value: " + value + ", left: " + l + ", right: " + r + "}"; 35 | } 36 | } 37 | 38 | class EmptyTree extends Tree { 39 | EmptyTree() { 40 | super(null, null, null, null); 41 | } 42 | 43 | Tree insert(String key, Object binding) { 44 | return new Tree(new EmptyTree(), key, binding, new EmptyTree()); 45 | } 46 | public String toString() { 47 | return ""; 48 | } 49 | } 50 | 51 | class Exer { 52 | 53 | public static void main(String[] args) { 54 | Tree t = new EmptyTree(); 55 | String[] letters = { "t", "s", "p", "i", "p", "f", "b", "s", "t"}; 56 | //String[] letters = { "a", "b", "c", "d", "e", "f", "g", "h", "i"}; 57 | for(int i=0; i< letters.length; ++i) { 58 | t = t.insert(letters[i], letters[i].hashCode()); 59 | } 60 | System.out.println(t); 61 | //for(int i=0; i< letters.length; ++i) { 62 | // System.out.println("Tree contains '" + letters[i] + "': " + t.member(letters[i])); 63 | //} 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /chap2/Parse/Main.java: -------------------------------------------------------------------------------- 1 | package Parse; 2 | 3 | public class Main { 4 | 5 | public static void main(String argv[]) throws java.io.IOException { 6 | String filename = argv[0]; 7 | ErrorMsg.ErrorMsg errorMsg = new ErrorMsg.ErrorMsg(filename); 8 | java.io.InputStream inp=new java.io.FileInputStream(filename); 9 | Lexer lexer = new Yylex(inp,errorMsg); 10 | java_cup.runtime.Symbol tok; 11 | 12 | do { 13 | tok=lexer.nextToken(); 14 | System.out.println(symnames[tok.sym] + " " + tok.left); 15 | } while (tok.sym != sym.EOF); 16 | 17 | inp.close(); 18 | } 19 | 20 | static String symnames[] = new String[100]; 21 | static { 22 | 23 | symnames[sym.FUNCTION] = "FUNCTION"; 24 | symnames[sym.EOF] = "EOF"; 25 | symnames[sym.INT] = "INT"; 26 | symnames[sym.GT] = "GT"; 27 | symnames[sym.DIVIDE] = "DIVIDE"; 28 | symnames[sym.COLON] = "COLON"; 29 | symnames[sym.ELSE] = "ELSE"; 30 | symnames[sym.OR] = "OR"; 31 | symnames[sym.NIL] = "NIL"; 32 | symnames[sym.DO] = "DO"; 33 | symnames[sym.GE] = "GE"; 34 | symnames[sym.error] = "error"; 35 | symnames[sym.LT] = "LT"; 36 | symnames[sym.OF] = "OF"; 37 | symnames[sym.MINUS] = "MINUS"; 38 | symnames[sym.ARRAY] = "ARRAY"; 39 | symnames[sym.TYPE] = "TYPE"; 40 | symnames[sym.FOR] = "FOR"; 41 | symnames[sym.TO] = "TO"; 42 | symnames[sym.TIMES] = "TIMES"; 43 | symnames[sym.COMMA] = "COMMA"; 44 | symnames[sym.LE] = "LE"; 45 | symnames[sym.IN] = "IN"; 46 | symnames[sym.END] = "END"; 47 | symnames[sym.ASSIGN] = "ASSIGN"; 48 | symnames[sym.STRING] = "STRING"; 49 | symnames[sym.DOT] = "DOT"; 50 | symnames[sym.LPAREN] = "LPAREN"; 51 | symnames[sym.RPAREN] = "RPAREN"; 52 | symnames[sym.IF] = "IF"; 53 | symnames[sym.SEMICOLON] = "SEMICOLON"; 54 | symnames[sym.ID] = "ID"; 55 | symnames[sym.WHILE] = "WHILE"; 56 | symnames[sym.LBRACK] = "LBRACK"; 57 | symnames[sym.RBRACK] = "RBRACK"; 58 | symnames[sym.NEQ] = "NEQ"; 59 | symnames[sym.VAR] = "VAR"; 60 | symnames[sym.BREAK] = "BREAK"; 61 | symnames[sym.AND] = "AND"; 62 | symnames[sym.PLUS] = "PLUS"; 63 | symnames[sym.LBRACE] = "LBRACE"; 64 | symnames[sym.RBRACE] = "RBRACE"; 65 | symnames[sym.LET] = "LET"; 66 | symnames[sym.THEN] = "THEN"; 67 | symnames[sym.EQ] = "EQ"; 68 | } 69 | 70 | } 71 | 72 | 73 | -------------------------------------------------------------------------------- /chap8/Canon/TraceSchedule.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | public class TraceSchedule { 4 | 5 | public Tree.StmList stms; 6 | BasicBlocks theBlocks; 7 | java.util.Dictionary table = new java.util.Hashtable(); 8 | 9 | Tree.StmList getLast(Tree.StmList block) { 10 | Tree.StmList l=block; 11 | while (l.tail.tail!=null) l=l.tail; 12 | return l; 13 | } 14 | 15 | void trace(Tree.StmList l) { 16 | for(;;) { 17 | Tree.LABEL lab = (Tree.LABEL)l.head; 18 | table.remove(lab.label); 19 | Tree.StmList last = getLast(l); 20 | Tree.Stm s = last.tail.head; 21 | if (s instanceof Tree.JUMP) { 22 | Tree.JUMP j = (Tree.JUMP)s; 23 | Tree.StmList target = (Tree.StmList)table.get(j.targets.head); 24 | if (j.targets.tail==null && target!=null) { 25 | last.tail=target; 26 | l=target; 27 | } 28 | else { 29 | last.tail.tail=getNext(); 30 | return; 31 | } 32 | } 33 | else if (s instanceof Tree.CJUMP) { 34 | Tree.CJUMP j = (Tree.CJUMP)s; 35 | Tree.StmList t = (Tree.StmList)table.get(j.iftrue); 36 | Tree.StmList f = (Tree.StmList)table.get(j.iffalse); 37 | if (f!=null) { 38 | last.tail.tail=f; 39 | l=f; 40 | } 41 | else if (t!=null) { 42 | last.tail.head=new Tree.CJUMP(Tree.CJUMP.notRel(j.relop), 43 | j.left,j.right, 44 | j.iffalse,j.iftrue); 45 | last.tail.tail=t; 46 | l=t; 47 | } 48 | else { 49 | Temp.Label ff = new Temp.Label(); 50 | last.tail.head=new Tree.CJUMP(j.relop,j.left,j.right, 51 | j.iftrue,ff); 52 | last.tail.tail=new Tree.StmList(new Tree.LABEL(ff), 53 | new Tree.StmList(new Tree.JUMP(j.iffalse), 54 | getNext())); 55 | return; 56 | } 57 | } 58 | else throw new Error("Bad basic block in TraceSchedule"); 59 | } 60 | } 61 | 62 | Tree.StmList getNext() { 63 | if (theBlocks.blocks==null) 64 | return new Tree.StmList(new Tree.LABEL(theBlocks.done), null); 65 | else { 66 | Tree.StmList s = theBlocks.blocks.head; 67 | Tree.LABEL lab = (Tree.LABEL)s.head; 68 | if (table.get(lab.label) != null) { 69 | trace(s); 70 | return s; 71 | } 72 | else { 73 | theBlocks.blocks = theBlocks.blocks.tail; 74 | return getNext(); 75 | } 76 | } 77 | } 78 | 79 | public TraceSchedule(BasicBlocks b) { 80 | theBlocks=b; 81 | for(StmListList l = b.blocks; l!=null; l=l.tail) 82 | table.put(((Tree.LABEL)l.head.head).label, l.head); 83 | stms=getNext(); 84 | table=null; 85 | } 86 | } 87 | 88 | 89 | -------------------------------------------------------------------------------- /chap9/Canon/TraceSchedule.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | public class TraceSchedule { 4 | 5 | public Tree.StmList stms; 6 | BasicBlocks theBlocks; 7 | java.util.Dictionary table = new java.util.Hashtable(); 8 | 9 | Tree.StmList getLast(Tree.StmList block) { 10 | Tree.StmList l=block; 11 | while (l.tail.tail!=null) l=l.tail; 12 | return l; 13 | } 14 | 15 | void trace(Tree.StmList l) { 16 | for(;;) { 17 | Tree.LABEL lab = (Tree.LABEL)l.head; 18 | table.remove(lab.label); 19 | Tree.StmList last = getLast(l); 20 | Tree.Stm s = last.tail.head; 21 | if (s instanceof Tree.JUMP) { 22 | Tree.JUMP j = (Tree.JUMP)s; 23 | Tree.StmList target = (Tree.StmList)table.get(j.targets.head); 24 | if (j.targets.tail==null && target!=null) { 25 | last.tail=target; 26 | l=target; 27 | } 28 | else { 29 | last.tail.tail=getNext(); 30 | return; 31 | } 32 | } 33 | else if (s instanceof Tree.CJUMP) { 34 | Tree.CJUMP j = (Tree.CJUMP)s; 35 | Tree.StmList t = (Tree.StmList)table.get(j.iftrue); 36 | Tree.StmList f = (Tree.StmList)table.get(j.iffalse); 37 | if (f!=null) { 38 | last.tail.tail=f; 39 | l=f; 40 | } 41 | else if (t!=null) { 42 | last.tail.head=new Tree.CJUMP(Tree.CJUMP.notRel(j.relop), 43 | j.left,j.right, 44 | j.iffalse,j.iftrue); 45 | last.tail.tail=t; 46 | l=t; 47 | } 48 | else { 49 | Temp.Label ff = new Temp.Label(); 50 | last.tail.head=new Tree.CJUMP(j.relop,j.left,j.right, 51 | j.iftrue,ff); 52 | last.tail.tail=new Tree.StmList(new Tree.LABEL(ff), 53 | new Tree.StmList(new Tree.JUMP(j.iffalse), 54 | getNext())); 55 | return; 56 | } 57 | } 58 | else throw new Error("Bad basic block in TraceSchedule"); 59 | } 60 | } 61 | 62 | Tree.StmList getNext() { 63 | if (theBlocks.blocks==null) 64 | return new Tree.StmList(new Tree.LABEL(theBlocks.done), null); 65 | else { 66 | Tree.StmList s = theBlocks.blocks.head; 67 | Tree.LABEL lab = (Tree.LABEL)s.head; 68 | if (table.get(lab.label) != null) { 69 | trace(s); 70 | return s; 71 | } 72 | else { 73 | theBlocks.blocks = theBlocks.blocks.tail; 74 | return getNext(); 75 | } 76 | } 77 | } 78 | 79 | public TraceSchedule(BasicBlocks b) { 80 | theBlocks=b; 81 | for(StmListList l = b.blocks; l!=null; l=l.tail) 82 | table.put(((Tree.LABEL)l.head.head).label, l.head); 83 | stms=getNext(); 84 | table=null; 85 | } 86 | } 87 | 88 | 89 | -------------------------------------------------------------------------------- /chap12/runtime.c: -------------------------------------------------------------------------------- 1 | #undef __STDC__ 2 | #include 3 | 4 | 5 | int *initArray(int size, int init) 6 | {int i; 7 | int *a = (int *)malloc(size*sizeof(int)); 8 | for(i=0;ilength!=t->length) return 0; 26 | for(i=0;ilength;i++) if (s->chars[i]!=t->chars[i]) return 0; 27 | return 1; 28 | } 29 | 30 | void print(struct string *s) 31 | {int i; unsigned char *p=s->chars; 32 | for(i=0;ilength;i++,p++) putchar(*p); 33 | } 34 | 35 | void flush() 36 | { 37 | fflush(stdout); 38 | } 39 | 40 | struct string consts[256]; 41 | struct string empty={0,""}; 42 | 43 | int main() 44 | {int i; 45 | for(i=0;i<256;i++) 46 | {consts[i].length=1; 47 | consts[i].chars[0]=i; 48 | } 49 | return tigermain(0 /* static link!? */); 50 | } 51 | 52 | int ord(struct string *s) 53 | { 54 | if (s->length==0) return -1; 55 | else return s->chars[0]; 56 | } 57 | 58 | struct string *chr(int i) 59 | { 60 | if (i<0 || i>=256) 61 | {printf("chr(%d) out of range\n",i); exit(1);} 62 | return consts+i; 63 | } 64 | 65 | int size(struct string *s) 66 | { 67 | return s->length; 68 | } 69 | 70 | struct string *substring(struct string *s, int first, int n) 71 | { 72 | if (first<0 || first+n>s->length) 73 | {printf("substring([%d],%d,%d) out of range\n",s->length,first,n); 74 | exit(1);} 75 | if (n==1) return consts+s->chars[first]; 76 | {struct string *t = (struct string *)malloc(sizeof(int)+n); 77 | int i; 78 | t->length=n; 79 | for(i=0;ichars[i]=s->chars[first+i]; 80 | return t; 81 | } 82 | } 83 | 84 | struct string *concat(struct string *a, struct string *b) 85 | { 86 | if (a->length==0) return b; 87 | else if (b->length==0) return a; 88 | else {int i, n=a->length+b->length; 89 | struct string *t = (struct string *)malloc(sizeof(int)+n); 90 | t->length=n; 91 | for (i=0;ilength;i++) 92 | t->chars[i]=a->chars[i]; 93 | for(i=0;ilength;i++) 94 | t->chars[i+a->length]=b->chars[i]; 95 | return t; 96 | } 97 | } 98 | 99 | int not(int i) 100 | { return !i; 101 | } 102 | 103 | #undef getchar 104 | 105 | struct string *getchar() 106 | {int i=getc(stdin); 107 | if (i==EOF) return ∅ 108 | else return consts+i; 109 | } 110 | -------------------------------------------------------------------------------- /chap9/Main/Main.java: -------------------------------------------------------------------------------- 1 | package Main; 2 | import Semant.Semant; 3 | import Translate.Translate; 4 | import Parse.Parse; 5 | 6 | class Main { 7 | 8 | static Frame.Frame frame = new .Frame(); 9 | 10 | static void prStmList(Tree.Print print, Tree.StmList stms) { 11 | for(Tree.StmList l = stms; l!=null; l=l.tail) 12 | print.prStm(l.head); 13 | } 14 | 15 | static Assem.InstrList codegen(Frame.Frame f, Tree.StmList stms) { 16 | Assem.InstrList first=null, last=null; 17 | for(Tree.StmList s=stms; s!=null; s=s.tail) { 18 | Assem.InstrList i = f.codegen(s.head); 19 | if (last==null) {first=last=i;} 20 | else {while (last.tail!=null) last=last.tail; 21 | last=last.tail=i; 22 | } 23 | } 24 | return first; 25 | } 26 | 27 | 28 | static void emitProc(java.io.PrintStream out, Translate.ProcFrag f) { 29 | java.io.PrintStream debug = 30 | /* new java.io.PrintStream(new NullOutputStream()); */ 31 | out; 32 | Temp.TempMap tempmap= new Temp.CombineMap(f.frame,new Temp.DefaultMap()); 33 | Tree.Print print = new Tree.Print(debug, tempmap); 34 | debug.println("# Before canonicalization: "); 35 | print.prStm(f.body); 36 | debug.print("# After canonicalization: "); 37 | Tree.StmList stms = Canon.Canon.linearize(f.body); 38 | prStmList(print,stms); 39 | debug.println("# Basic Blocks: "); 40 | Canon.BasicBlocks b = new Canon.BasicBlocks(stms); 41 | for(Canon.StmListList l = b.blocks; l!=null; l=l.tail) { 42 | debug.println("#"); 43 | prStmList(print,l.head); 44 | } 45 | print.prStm(new Tree.LABEL(b.done)); 46 | debug.println("# Trace Scheduled: "); 47 | Tree.StmList traced = (new Canon.TraceSchedule(b)).stms; 48 | prStmList(print,traced); 49 | Assem.InstrList instrs= codegen(f.frame,traced); 50 | debug.println("# Instructions: "); 51 | for(Assem.InstrList p=instrs; p!=null; p=p.tail) 52 | debug.print(p.head.format(tempmap)); 53 | } 54 | 55 | public static void main(String args[]) throws java.io.IOException { 56 | Parse.Parse parse = new Parse.Parse(args[0]); 57 | java.io.PrintStream out = 58 | new java.io.PrintStream(new java.io.FileOutputStream(args[0] + ".s")); 59 | Translate.Translate translate = new Translate.Translate(frame); 60 | Semant semant = new Semant(translate,parse.errorMsg); 61 | Translate.Frag frags = semant.transProg(parse.absyn); 62 | for(Translate.Frag f = frags; f!=null; f=f.next) 63 | if (f instanceof Translate.ProcFrag) 64 | emitProc(out, (Translate.ProcFrag)f); 65 | else if (f instanceof Translate.DataFrag) 66 | out.print(((Translate.DataFrag)f).data); 67 | out.close(); 68 | } 69 | 70 | } 71 | 72 | class NullOutputStream extends java.io.OutputStream { 73 | public void write(int b) {} 74 | } 75 | 76 | 77 | -------------------------------------------------------------------------------- /chap1/slp.java: -------------------------------------------------------------------------------- 1 | abstract class Stm { 2 | abstract int maxargs(); 3 | abstract Table interp(Table t); 4 | } 5 | 6 | class CompoundStm extends Stm { 7 | Stm stm1, stm2; 8 | CompoundStm(Stm s1, Stm s2) {stm1=s1; stm2=s2;} 9 | int maxargs() { 10 | return Math.max(stm1.maxargs(), stm2.maxargs()); 11 | } 12 | 13 | Table interp(Table t) { 14 | return stm2.interp(stm1.interp(t)); 15 | } 16 | } 17 | 18 | class AssignStm extends Stm { 19 | String id; Exp exp; 20 | AssignStm(String i, Exp e) {id=i; exp=e;} 21 | int maxargs() { 22 | return exp.maxargs(); 23 | } 24 | Table interp(Table t) { 25 | IntAndTable it = exp.interp(t); 26 | return new Table(id, it.i, t); 27 | } 28 | } 29 | 30 | class PrintStm extends Stm { 31 | ExpList exps; 32 | PrintStm(ExpList e) {exps=e;} 33 | int maxargs() { 34 | return Math.max(exps.size(), exps.maxargs()); 35 | } 36 | 37 | Table interp(Table t) { 38 | ExpList head = exps; 39 | Table current_table = t; 40 | while (head != null) { 41 | IntAndTable head_it = head.interp(current_table); 42 | System.out.print(head_it.i); 43 | head = head.next(); 44 | current_table = head_it.t; 45 | if (head != null) System.out.print(" "); 46 | } 47 | System.out.println(); 48 | return current_table; 49 | } 50 | } 51 | 52 | abstract class Exp { 53 | abstract int maxargs(); 54 | abstract IntAndTable interp(Table t); 55 | } 56 | 57 | class IdExp extends Exp { 58 | String id; 59 | IdExp(String i) {id=i;} 60 | int maxargs() { 61 | return 0; 62 | } 63 | IntAndTable interp(Table t) { 64 | return new IntAndTable(t.lookup(id), t); 65 | } 66 | } 67 | 68 | class NumExp extends Exp { 69 | int num; 70 | NumExp(int n) {num=n;} 71 | int maxargs() { 72 | return 0; 73 | } 74 | IntAndTable interp(Table t) { 75 | return new IntAndTable(num, t); 76 | } 77 | } 78 | 79 | class OpExp extends Exp { 80 | Exp left, right; int oper; 81 | final static int Plus=1,Minus=2,Times=3,Div=4; 82 | OpExp(Exp l, int o, Exp r) {left=l; oper=o; right=r;} 83 | int maxargs() { 84 | return Math.max(left.maxargs(), right.maxargs()); 85 | } 86 | IntAndTable interp(Table t) { 87 | IntAndTable left_it = left.interp(t); 88 | IntAndTable right_it = right.interp(left_it.t); 89 | 90 | int l = left_it.i; 91 | int r = right_it.i; 92 | 93 | int num = (Plus == oper) ? l + r : (Minus == oper) ? l - r : (Times == oper) ? l * r : (Div == oper) ? l / r : 0; 94 | return new IntAndTable(num, right_it.t); 95 | } 96 | } 97 | 98 | class EseqExp extends Exp { 99 | Stm stm; Exp exp; 100 | EseqExp(Stm s, Exp e) {stm=s; exp=e;} 101 | int maxargs() { 102 | return Math.max(stm.maxargs(), exp.maxargs()); 103 | } 104 | IntAndTable interp(Table t) { 105 | Table t2 = stm.interp(t); 106 | return exp.interp(t2); 107 | } 108 | } 109 | 110 | abstract class ExpList { 111 | abstract int size(); 112 | abstract int maxargs(); 113 | abstract IntAndTable interp(Table t); 114 | ExpList next() { 115 | return null; 116 | } 117 | } 118 | 119 | class PairExpList extends ExpList { 120 | Exp head; ExpList tail; 121 | public PairExpList(Exp h, ExpList t) {head=h; tail=t;} 122 | 123 | int size() { 124 | return 1 + tail.size(); 125 | } 126 | int maxargs() { 127 | return Math.max(head.maxargs(), tail.maxargs()); 128 | } 129 | IntAndTable interp(Table t) { 130 | return head.interp(t); 131 | } 132 | ExpList next() { 133 | return tail; 134 | } 135 | } 136 | 137 | class LastExpList extends ExpList { 138 | Exp head; 139 | public LastExpList(Exp h) {head=h;} 140 | 141 | int size() { 142 | return 1; 143 | } 144 | 145 | int maxargs() { 146 | return head.maxargs(); 147 | } 148 | 149 | IntAndTable interp(Table t) { 150 | return head.interp(t); 151 | } 152 | } -------------------------------------------------------------------------------- /chap8/Canon/Canon.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | class MoveCall extends Tree.Stm { 4 | Tree.TEMP dst; 5 | Tree.CALL src; 6 | MoveCall(Tree.TEMP d, Tree.CALL s) {dst=d; src=s;} 7 | public Tree.ExpList kids() {return src.kids();} 8 | public Tree.Stm build(Tree.ExpList kids) { 9 | return new Tree.MOVE(dst, src.build(kids)); 10 | } 11 | } 12 | 13 | class ExpCall extends Tree.Stm { 14 | Tree.CALL call; 15 | ExpCall(Tree.CALL c) {call=c;} 16 | public Tree.ExpList kids() {return call.kids();} 17 | public Tree.Stm build(Tree.ExpList kids) { 18 | return new Tree.EXP(call.build(kids)); 19 | } 20 | } 21 | 22 | class StmExpList { 23 | Tree.Stm stm; 24 | Tree.ExpList exps; 25 | StmExpList(Tree.Stm s, Tree.ExpList e) {stm=s; exps=e;} 26 | } 27 | 28 | public class Canon { 29 | 30 | static boolean isNop(Tree.Stm a) { 31 | return a instanceof Tree.EXP 32 | && ((Tree.EXP)a).exp instanceof Tree.CONST; 33 | } 34 | 35 | static Tree.Stm seq(Tree.Stm a, Tree.Stm b) { 36 | if (isNop(a)) return b; 37 | else if (isNop(b)) return a; 38 | else return new Tree.SEQ(a,b); 39 | } 40 | 41 | static boolean commute(Tree.Stm a, Tree.Exp b) { 42 | return isNop(a) 43 | || b instanceof Tree.NAME 44 | || b instanceof Tree.CONST; 45 | } 46 | 47 | static Tree.Stm do_stm(Tree.SEQ s) { 48 | return seq(do_stm(s.left), do_stm(s.right)); 49 | } 50 | 51 | static Tree.Stm do_stm(Tree.MOVE s) { 52 | if (s.dst instanceof Tree.TEMP 53 | && s.src instanceof Tree.CALL) 54 | return reorder_stm(new MoveCall((Tree.TEMP)s.dst, 55 | (Tree.CALL)s.src)); 56 | else if (s.dst instanceof Tree.ESEQ) 57 | return do_stm(new Tree.SEQ(((Tree.ESEQ)s.dst).stm, 58 | new Tree.MOVE(((Tree.ESEQ)s.dst).exp, 59 | s.src))); 60 | else return reorder_stm(s); 61 | } 62 | 63 | static Tree.Stm do_stm(Tree.EXP s) { 64 | if (s.exp instanceof Tree.CALL) 65 | return reorder_stm(new ExpCall((Tree.CALL)s.exp)); 66 | else return reorder_stm(s); 67 | } 68 | 69 | static Tree.Stm do_stm(Tree.Stm s) { 70 | if (s instanceof Tree.SEQ) return do_stm((Tree.SEQ)s); 71 | else if (s instanceof Tree.MOVE) return do_stm((Tree.MOVE)s); 72 | else if (s instanceof Tree.EXP) return do_stm((Tree.EXP)s); 73 | else return reorder_stm(s); 74 | } 75 | 76 | static Tree.Stm reorder_stm(Tree.Stm s) { 77 | StmExpList x = reorder(s.kids()); 78 | return seq(x.stm, s.build(x.exps)); 79 | } 80 | 81 | static Tree.ESEQ do_exp(Tree.ESEQ e) { 82 | Tree.Stm stms = do_stm(e.stm); 83 | Tree.ESEQ b = do_exp(e.exp); 84 | return new Tree.ESEQ(seq(stms,b.stm), b.exp); 85 | } 86 | 87 | static Tree.ESEQ do_exp (Tree.Exp e) { 88 | if (e instanceof Tree.ESEQ) return do_exp((Tree.ESEQ)e); 89 | else return reorder_exp(e); 90 | } 91 | 92 | static Tree.ESEQ reorder_exp (Tree.Exp e) { 93 | StmExpList x = reorder(e.kids()); 94 | return new Tree.ESEQ(x.stm, e.build(x.exps)); 95 | } 96 | 97 | static StmExpList nopNull = new StmExpList(new Tree.EXP(new Tree.CONST(0)),null); 98 | 99 | static StmExpList reorder(Tree.ExpList exps) { 100 | if (exps==null) return nopNull; 101 | else { 102 | Tree.Exp a = exps.head; 103 | if (a instanceof Tree.CALL) { 104 | Temp.Temp t = new Temp.Temp(); 105 | Tree.Exp e = new Tree.ESEQ(new Tree.MOVE(new Tree.TEMP(t), a), 106 | new Tree.TEMP(t)); 107 | return reorder(new Tree.ExpList(e, exps.tail)); 108 | } else { 109 | Tree.ESEQ aa = do_exp(a); 110 | StmExpList bb = reorder(exps.tail); 111 | if (commute(bb.stm, aa.exp)) 112 | return new StmExpList(seq(aa.stm,bb.stm), 113 | new Tree.ExpList(aa.exp,bb.exps)); 114 | else { 115 | Temp.Temp t = new Temp.Temp(); 116 | return new StmExpList( 117 | seq(aa.stm, 118 | seq(new Tree.MOVE(new Tree.TEMP(t),aa.exp), 119 | bb.stm)), 120 | new Tree.ExpList(new Tree.TEMP(t), bb.exps)); 121 | } 122 | } 123 | } 124 | } 125 | 126 | static Tree.StmList linear(Tree.SEQ s, Tree.StmList l) { 127 | return linear(s.left,linear(s.right,l)); 128 | } 129 | static Tree.StmList linear(Tree.Stm s, Tree.StmList l) { 130 | if (s instanceof Tree.SEQ) return linear((Tree.SEQ)s, l); 131 | else return new Tree.StmList(s,l); 132 | } 133 | 134 | static public Tree.StmList linearize(Tree.Stm s) { 135 | return linear(do_stm(s), null); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /chap9/Canon/Canon.java: -------------------------------------------------------------------------------- 1 | package Canon; 2 | 3 | class MoveCall extends Tree.Stm { 4 | Tree.TEMP dst; 5 | Tree.CALL src; 6 | MoveCall(Tree.TEMP d, Tree.CALL s) {dst=d; src=s;} 7 | public Tree.ExpList kids() {return src.kids();} 8 | public Tree.Stm build(Tree.ExpList kids) { 9 | return new Tree.MOVE(dst, src.build(kids)); 10 | } 11 | } 12 | 13 | class ExpCall extends Tree.Stm { 14 | Tree.CALL call; 15 | ExpCall(Tree.CALL c) {call=c;} 16 | public Tree.ExpList kids() {return call.kids();} 17 | public Tree.Stm build(Tree.ExpList kids) { 18 | return new Tree.EXP(call.build(kids)); 19 | } 20 | } 21 | 22 | class StmExpList { 23 | Tree.Stm stm; 24 | Tree.ExpList exps; 25 | StmExpList(Tree.Stm s, Tree.ExpList e) {stm=s; exps=e;} 26 | } 27 | 28 | public class Canon { 29 | 30 | static boolean isNop(Tree.Stm a) { 31 | return a instanceof Tree.EXP 32 | && ((Tree.EXP)a).exp instanceof Tree.CONST; 33 | } 34 | 35 | static Tree.Stm seq(Tree.Stm a, Tree.Stm b) { 36 | if (isNop(a)) return b; 37 | else if (isNop(b)) return a; 38 | else return new Tree.SEQ(a,b); 39 | } 40 | 41 | static boolean commute(Tree.Stm a, Tree.Exp b) { 42 | return isNop(a) 43 | || b instanceof Tree.NAME 44 | || b instanceof Tree.CONST; 45 | } 46 | 47 | static Tree.Stm do_stm(Tree.SEQ s) { 48 | return seq(do_stm(s.left), do_stm(s.right)); 49 | } 50 | 51 | static Tree.Stm do_stm(Tree.MOVE s) { 52 | if (s.dst instanceof Tree.TEMP 53 | && s.src instanceof Tree.CALL) 54 | return reorder_stm(new MoveCall((Tree.TEMP)s.dst, 55 | (Tree.CALL)s.src)); 56 | else if (s.dst instanceof Tree.ESEQ) 57 | return do_stm(new Tree.SEQ(((Tree.ESEQ)s.dst).stm, 58 | new Tree.MOVE(((Tree.ESEQ)s.dst).exp, 59 | s.src))); 60 | else return reorder_stm(s); 61 | } 62 | 63 | static Tree.Stm do_stm(Tree.EXP s) { 64 | if (s.exp instanceof Tree.CALL) 65 | return reorder_stm(new ExpCall((Tree.CALL)s.exp)); 66 | else return reorder_stm(s); 67 | } 68 | 69 | static Tree.Stm do_stm(Tree.Stm s) { 70 | if (s instanceof Tree.SEQ) return do_stm((Tree.SEQ)s); 71 | else if (s instanceof Tree.MOVE) return do_stm((Tree.MOVE)s); 72 | else if (s instanceof Tree.EXP) return do_stm((Tree.EXP)s); 73 | else return reorder_stm(s); 74 | } 75 | 76 | static Tree.Stm reorder_stm(Tree.Stm s) { 77 | StmExpList x = reorder(s.kids()); 78 | return seq(x.stm, s.build(x.exps)); 79 | } 80 | 81 | static Tree.ESEQ do_exp(Tree.ESEQ e) { 82 | Tree.Stm stms = do_stm(e.stm); 83 | Tree.ESEQ b = do_exp(e.exp); 84 | return new Tree.ESEQ(seq(stms,b.stm), b.exp); 85 | } 86 | 87 | static Tree.ESEQ do_exp (Tree.Exp e) { 88 | if (e instanceof Tree.ESEQ) return do_exp((Tree.ESEQ)e); 89 | else return reorder_exp(e); 90 | } 91 | 92 | static Tree.ESEQ reorder_exp (Tree.Exp e) { 93 | StmExpList x = reorder(e.kids()); 94 | return new Tree.ESEQ(x.stm, e.build(x.exps)); 95 | } 96 | 97 | static StmExpList nopNull = new StmExpList(new Tree.EXP(new Tree.CONST(0)),null); 98 | 99 | static StmExpList reorder(Tree.ExpList exps) { 100 | if (exps==null) return nopNull; 101 | else { 102 | Tree.Exp a = exps.head; 103 | if (a instanceof Tree.CALL) { 104 | Temp.Temp t = new Temp.Temp(); 105 | Tree.Exp e = new Tree.ESEQ(new Tree.MOVE(new Tree.TEMP(t), a), 106 | new Tree.TEMP(t)); 107 | return reorder(new Tree.ExpList(e, exps.tail)); 108 | } else { 109 | Tree.ESEQ aa = do_exp(a); 110 | StmExpList bb = reorder(exps.tail); 111 | if (commute(bb.stm, aa.exp)) 112 | return new StmExpList(seq(aa.stm,bb.stm), 113 | new Tree.ExpList(aa.exp,bb.exps)); 114 | else { 115 | Temp.Temp t = new Temp.Temp(); 116 | return new StmExpList( 117 | seq(aa.stm, 118 | seq(new Tree.MOVE(new Tree.TEMP(t),aa.exp), 119 | bb.stm)), 120 | new Tree.ExpList(new Tree.TEMP(t), bb.exps)); 121 | } 122 | } 123 | } 124 | } 125 | 126 | static Tree.StmList linear(Tree.SEQ s, Tree.StmList l) { 127 | return linear(s.left,linear(s.right,l)); 128 | } 129 | static Tree.StmList linear(Tree.Stm s, Tree.StmList l) { 130 | if (s instanceof Tree.SEQ) return linear((Tree.SEQ)s, l); 131 | else return new Tree.StmList(s,l); 132 | } 133 | 134 | static public Tree.StmList linearize(Tree.Stm s) { 135 | return linear(do_stm(s), null); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /chap7/Tree/Print.java: -------------------------------------------------------------------------------- 1 | package Tree; 2 | 3 | public class Print { 4 | 5 | java.io.PrintStream out; 6 | Temp.TempMap tmap; 7 | 8 | public Print(java.io.PrintStream o, Temp.TempMap t) {out=o; tmap=t;} 9 | 10 | public Print(java.io.PrintStream o) {out=o; tmap=new Temp.DefaultMap();} 11 | 12 | void indent(int d) { 13 | for(int i=0; i