diff --git a/tiger/chap1/slp.sml b/tiger/chap1/slp.sml new file mode 100644 index 0000000..0d76c74 --- /dev/null +++ b/tiger/chap1/slp.sml @@ -0,0 +1,20 @@ +type id = string + +datatype binop = Plus | Minus | Times | Div + +datatype stm = CompoundStm of stm * stm + | AssignStm of id * exp + | PrintStm of exp list + + and exp = IdExp of id + | NumExp of int + | OpExp of exp * binop * exp + | EseqExp of stm * exp +val prog = + CompoundStm(AssignStm("a",OpExp(NumExp 5, Plus, NumExp 3)), + CompoundStm(AssignStm("b", + EseqExp(PrintStm[IdExp"a",OpExp(IdExp"a", Minus,NumExp 1)], + OpExp(NumExp 10, Times, IdExp"a"))), + PrintStm[IdExp "b"])) + + diff --git a/tiger/chap10/graph.sml b/tiger/chap10/graph.sml new file mode 100644 index 0000000..a2b6d5c --- /dev/null +++ b/tiger/chap10/graph.sml @@ -0,0 +1,80 @@ +structure Graph :> GRAPH = +struct + type node' = int + type temp = Temp.temp + + datatype noderep = NODE of {succ: node' list, pred: node' list} + + val emptyNode = NODE{succ=[],pred=[]} + + val bogusNode = NODE{succ=[~1],pred=[]} + + fun isBogus(NODE{succ= ~1::_,...}) = true + | isBogus _ = false + + structure A = DynamicArrayFn(struct open Array + type elem = noderep + type vector = noderep vector + type array = noderep array + end) + + type graph = A.array + + type node = graph * node' + fun eq((_,a),(_,b)) = a=b + + fun augment (g: graph) (n: node') : node = (g,n) + + fun newGraph() = A.array(0,bogusNode) + + fun nodes g = let val b = A.bound g + fun f i = if isBogus( A.sub(g,i)) then nil + else (g,i)::f(i+1) + in f 0 + end + + fun succ(g,i) = let val NODE{succ=s,...} = A.sub(g,i) + in map (augment g) s + end + fun pred(g,i) = let val NODE{pred=p,...} = A.sub(g,i) + in map (augment g) p + end + fun adj gi = pred gi @ succ gi + + fun newNode g = (* binary search for unused node *) + let fun look(lo,hi) = + (* i < lo indicates i in use + i >= hi indicates i not in use *) + if lo=hi then (A.update(g,lo,emptyNode); (g,lo)) + else let val m = (lo+hi) div 2 + in if isBogus(A.sub(g,m)) then look(lo,m) else look(m+1,hi) + end + in look(0, 1 + A.bound g) + end + + exception GraphEdge + fun check(g,g') = (* if g=g' then () else raise GraphEdge *) () + + fun delete(i,j::rest) = if i=j then rest else j::delete(i,rest) + | delete(_,nil) = raise GraphEdge + + fun diddle_edge change {from=(g:graph, i),to=(g':graph, j)} = + let val _ = check(g,g') + val NODE{succ=si,pred=pi} = A.sub(g,i) + val _ = A.update(g,i,NODE{succ=change(j,si),pred=pi}) + val NODE{succ=sj,pred=pj} = A.sub(g,j) + val _ = A.update(g,j,NODE{succ=sj,pred=change(i,pj)}) + in () + end + + val mk_edge = diddle_edge (op ::) + val rm_edge = diddle_edge delete + + structure Table = IntMapTable(type key = node + fun getInt(g,n) = n) + + + fun nodename(g,i:int) = "n" ^ Int.toString(i) + +end + diff --git a/tiger/chap12/runtime.c b/tiger/chap12/runtime.c new file mode 100644 index 0000000..106ad56 --- /dev/null +++ b/tiger/chap12/runtime.c @@ -0,0 +1,109 @@ +#undef __STDC__ +#include + + +int *initArray(int size, int init) +{int i; + int *a = (int *)malloc(size*sizeof(int)); + for(i=0;ilength!=t->length) return 0; + for(i=0;ilength;i++) if (s->chars[i]!=t->chars[i]) return 0; + return 1; +} + +void print(struct string *s) +{int i; unsigned char *p=s->chars; + for(i=0;ilength;i++,p++) putchar(*p); +} + +void flush() +{ + fflush(stdout); +} + +struct string consts[256]; +struct string empty={0,""}; + +int main() +{int i; + for(i=0;i<256;i++) + {consts[i].length=1; + consts[i].chars[0]=i; + } + return tigermain(0 /* static link!? */); +} + +int ord(struct string *s) +{ + if (s->length==0) return -1; + else return s->chars[0]; +} + +struct string *chr(int i) +{ + if (i<0 || i>=256) + {printf("chr(%d) out of range\n",i); exit(1);} + return consts+i; +} + +int size(struct string *s) +{ + return s->length; +} + +struct string *substring(struct string *s, int first, int n) +{ + if (first<0 || first+n>s->length) + {printf("substring([%d],%d,%d) out of range\n",s->length,first,n); + exit(1);} + if (n==1) return consts+s->chars[first]; + {struct string *t = (struct string *)malloc(sizeof(int)+n); + int i; + t->length=n; + for(i=0;ichars[i]=s->chars[first+i]; + return t; + } +} + +struct string *concat(struct string *a, struct string *b) +{ + if (a->length==0) return b; + else if (b->length==0) return a; + else {int i, n=a->length+b->length; + struct string *t = (struct string *)malloc(sizeof(int)+n); + t->length=n; + for (i=0;ilength;i++) + t->chars[i]=a->chars[i]; + for(i=0;ilength;i++) + t->chars[i+a->length]=b->chars[i]; + return t; + } +} + +int not(int i) +{ return !i; +} + +#undef getchar + +struct string *getchar() +{int i=getc(stdin); + if (i==EOF) return ∅ + else return consts+i; +} diff --git a/tiger/chap2/driver.sml b/tiger/chap2/driver.sml new file mode 100644 index 0000000..b974e9f --- /dev/null +++ b/tiger/chap2/driver.sml @@ -0,0 +1,17 @@ +structure Parse = +struct + fun parse filename = + let val file = TextIO.openIn filename + fun get _ = TextIO.input file + val lexer = Mlex.makeLexer get + fun do_it() = + let val t = lexer() + in print t; print "\n"; + if substring(t,0,3)="EOF" then () else do_it() + end + in do_it(); + TextIO.closeIn file + end + +end + diff --git a/tiger/chap2/errormsg.sml b/tiger/chap2/errormsg.sml new file mode 100644 index 0000000..8a744cd --- /dev/null +++ b/tiger/chap2/errormsg.sml @@ -0,0 +1,53 @@ +signature ERRORMSG = +sig + val anyErrors : bool ref + val fileName : string ref + val lineNum : int ref + val linePos : int list ref + val sourceStream : TextIO.instream ref + val error : int -> string -> unit + exception Error + val impossible : string -> 'a (* raises Error *) + val reset : unit -> unit +end + +structure ErrorMsg : ERRORMSG = +struct + + val anyErrors = ref false + val fileName = ref "" + val lineNum = ref 1 + val linePos = ref [1] + val sourceStream = ref TextIO.stdIn + + fun reset() = (anyErrors:=false; + fileName:=""; + lineNum:=1; + linePos:=[1]; + sourceStream:=TextIO.stdIn) + + exception Error + + fun error pos (msg:string) = + let fun look(a::rest,n) = + if a (lineNum := !lineNum+1; linePos := yypos :: !linePos; continue()); +"," => (Tokens.COMMA(yypos,yypos+1)); +var => (Tokens.VAR(yypos,yypos+3)); +"123" => (Tokens.INT(123,yypos,yypos+3)); +. => (ErrorMsg.error yypos ("illegal character " ^ yytext); continue()); + diff --git a/tiger/chap2/tokens.sig b/tiger/chap2/tokens.sig new file mode 100644 index 0000000..ed92f0b --- /dev/null +++ b/tiger/chap2/tokens.sig @@ -0,0 +1,49 @@ +signature Tiger_TOKENS = +sig +type linenum (* = int *) +type token +val TYPE: linenum * linenum -> token +val VAR: linenum * linenum -> token +val FUNCTION: linenum * linenum -> token +val BREAK: linenum * linenum -> token +val OF: linenum * linenum -> token +val END: linenum * linenum -> token +val IN: linenum * linenum -> token +val NIL: linenum * linenum -> token +val LET: linenum * linenum -> token +val DO: linenum * linenum -> token +val TO: linenum * linenum -> token +val FOR: linenum * linenum -> token +val WHILE: linenum * linenum -> token +val ELSE: linenum * linenum -> token +val THEN: linenum * linenum -> token +val IF: linenum * linenum -> token +val ARRAY: linenum * linenum -> token +val ASSIGN: linenum * linenum -> token +val OR: linenum * linenum -> token +val AND: linenum * linenum -> token +val GE: linenum * linenum -> token +val GT: linenum * linenum -> token +val LE: linenum * linenum -> token +val LT: linenum * linenum -> token +val NEQ: linenum * linenum -> token +val EQ: linenum * linenum -> token +val DIVIDE: linenum * linenum -> token +val TIMES: linenum * linenum -> token +val MINUS: linenum * linenum -> token +val PLUS: linenum * linenum -> token +val DOT: linenum * linenum -> token +val RBRACE: linenum * linenum -> token +val LBRACE: linenum * linenum -> token +val RBRACK: linenum * linenum -> token +val LBRACK: linenum * linenum -> token +val RPAREN: linenum * linenum -> token +val LPAREN: linenum * linenum -> token +val SEMICOLON: linenum * linenum -> token +val COLON: linenum * linenum -> token +val COMMA: linenum * linenum -> token +val STRING: (string) * linenum * linenum -> token +val INT: (int) * linenum * linenum -> token +val ID: (string) * linenum * linenum -> token +val EOF: linenum * linenum -> token +end diff --git a/tiger/chap2/tokens.sml b/tiger/chap2/tokens.sml new file mode 100644 index 0000000..b645a3d --- /dev/null +++ b/tiger/chap2/tokens.sml @@ -0,0 +1,51 @@ +structure Tokens : Tiger_TOKENS = +struct + (* A "scaffold" structure for debugging lexers. *) + +type linenum = int +type token = string +fun TYPE(i,j) = "TYPE " ^ Int.toString(i) +fun VAR(i,j) = "VAR " ^ Int.toString(i) +fun FUNCTION(i,j) = "FUNCTION " ^ Int.toString(i) +fun BREAK(i,j) = "BREAK " ^ Int.toString(i) +fun OF(i,j) = "OF " ^ Int.toString(i) +fun END(i,j) = "END " ^ Int.toString(i) +fun IN(i,j) = "IN " ^ Int.toString(i) +fun NIL(i,j) = "NIL " ^ Int.toString(i) +fun LET(i,j) = "LET " ^ Int.toString(i) +fun DO(i,j) = "DO " ^ Int.toString(i) +fun TO(i,j) = "TO " ^ Int.toString(i) +fun FOR(i,j) = "FOR " ^ Int.toString(i) +fun WHILE(i,j) = "WHILE " ^ Int.toString(i) +fun ELSE(i,j) = "ELSE " ^ Int.toString(i) +fun THEN(i,j) = "THEN " ^ Int.toString(i) +fun IF(i,j) = "IF " ^ Int.toString(i) +fun ARRAY(i,j) = "ARRAY " ^ Int.toString(i) +fun ASSIGN(i,j) = "ASSIGN " ^ Int.toString(i) +fun OR(i,j) = "OR " ^ Int.toString(i) +fun AND(i,j) = "AND " ^ Int.toString(i) +fun GE(i,j) = "GE " ^ Int.toString(i) +fun GT(i,j) = "GT " ^ Int.toString(i) +fun LE(i,j) = "LE " ^ Int.toString(i) +fun LT(i,j) = "LT " ^ Int.toString(i) +fun NEQ(i,j) = "NEQ " ^ Int.toString(i) +fun EQ(i,j) = "EQ " ^ Int.toString(i) +fun DIVIDE(i,j) = "DIVIDE " ^ Int.toString(i) +fun TIMES(i,j) = "TIMES " ^ Int.toString(i) +fun MINUS(i,j) = "MINUS " ^ Int.toString(i) +fun PLUS(i,j) = "PLUS " ^ Int.toString(i) +fun DOT(i,j) = "DOT " ^ Int.toString(i) +fun RBRACE(i,j) = "RBRACE " ^ Int.toString(i) +fun LBRACE(i,j) = "LBRACE " ^ Int.toString(i) +fun RBRACK(i,j) = "RBRACK " ^ Int.toString(i) +fun LBRACK(i,j) = "LBRACK " ^ Int.toString(i) +fun RPAREN(i,j) = "RPAREN " ^ Int.toString(i) +fun LPAREN(i,j) = "LPAREN " ^ Int.toString(i) +fun SEMICOLON(i,j) = "SEMICOLON " ^ Int.toString(i) +fun COLON(i,j) = "COLON " ^ Int.toString(i) +fun COMMA(i,j) = "COMMA " ^ Int.toString(i) +fun STRING(s,i,j) = "STRING("^s^") " ^ Int.toString(i) +fun INT(c,i,j) = "INT("^Int.toString(c)^") " ^ Int.toString(i) +fun ID(s,i,j) = "ID("^s^") " ^ Int.toString(i) +fun EOF(i,j) = "EOF " ^ Int.toString(i) +end diff --git a/tiger/chap3/errormsg.sml b/tiger/chap3/errormsg.sml new file mode 100644 index 0000000..8a744cd --- /dev/null +++ b/tiger/chap3/errormsg.sml @@ -0,0 +1,53 @@ +signature ERRORMSG = +sig + val anyErrors : bool ref + val fileName : string ref + val lineNum : int ref + val linePos : int list ref + val sourceStream : TextIO.instream ref + val error : int -> string -> unit + exception Error + val impossible : string -> 'a (* raises Error *) + val reset : unit -> unit +end + +structure ErrorMsg : ERRORMSG = +struct + + val anyErrors = ref false + val fileName = ref "" + val lineNum = ref 1 + val linePos = ref [1] + val sourceStream = ref TextIO.stdIn + + fun reset() = (anyErrors:=false; + fileName:=""; + lineNum:=1; + linePos:=[1]; + sourceStream:=TextIO.stdIn) + + exception Error + + fun error pos (msg:string) = + let fun look(a::rest,n) = + if a unit end = +struct + structure TigerLrVals = TigerLrValsFun(structure Token = LrParser.Token) + structure Lex = TigerLexFun(structure Tokens = TigerLrVals.Tokens) + structure TigerP = Join(structure ParserData = TigerLrVals.ParserData + structure Lex=Lex + structure LrParser = LrParser) + fun parse filename = + let val _ = (ErrorMsg.reset(); ErrorMsg.fileName := filename) + val file = TextIO.openIn filename + fun get _ = TextIO.input file + fun parseerror(s,p1,p2) = ErrorMsg.error p1 s + val lexer = LrParser.Stream.streamify (Lex.makeLexer get) + val (absyn, _) = TigerP.parse(30,lexer,parseerror,()) + in TextIO.closeIn file; + absyn + end handle LrParser.ParseError => raise ErrorMsg.Error + +end + + + diff --git a/tiger/chap3/sources.cm b/tiger/chap3/sources.cm new file mode 100644 index 0000000..5e85dba --- /dev/null +++ b/tiger/chap3/sources.cm @@ -0,0 +1,9 @@ +Group is + +tiger.lex +errormsg.sml +parsetest.sml +tiger.grm +smlnj-lib.cm +ml-yacc-lib.cm + diff --git a/tiger/chap3/tiger.grm b/tiger/chap3/tiger.grm new file mode 100644 index 0000000..455679c --- /dev/null +++ b/tiger/chap3/tiger.grm @@ -0,0 +1,38 @@ +%% +%term + EOF + | ID of string + | INT of int | STRING of string + | COMMA | COLON | SEMICOLON | LPAREN | RPAREN | LBRACK | RBRACK + | LBRACE | RBRACE | DOT + | PLUS | MINUS | TIMES | DIVIDE | EQ | NEQ | LT | LE | GT | GE + | AND | OR | ASSIGN + | ARRAY | IF | THEN | ELSE | WHILE | FOR | TO | DO | LET | IN | END | OF + | BREAK | NIL + | FUNCTION | VAR | TYPE + +%nonterm exp | program + +%pos int +%verbose +%start program +%eop EOF +%noshift EOF + +%name Tiger + +%keyword WHILE FOR TO BREAK LET IN END FUNCTION VAR TYPE ARRAY IF THEN ELSE + DO OF NIL + +%prefer THEN ELSE LPAREN + +%value ID ("bogus") +%value INT (1) +%value STRING ("") + +%% + +program : exp () + + +exp: () diff --git a/tiger/chap3/tiger.lex.sml b/tiger/chap3/tiger.lex.sml new file mode 100644 index 0000000..993abe8 --- /dev/null +++ b/tiger/chap3/tiger.lex.sml @@ -0,0 +1,988 @@ +(* Copyright (c) 1997 Andrew W. Appel. *) +functor TigerLexFun(structure Tokens : Tiger_TOKENS)= + struct + structure UserDeclarations = + struct +open ErrorMsg; + +type svalue = Tokens.svalue +type pos = int +type ('a,'b) token = ('a,'b) Tokens.token +type lexresult = (svalue,pos) token + +fun inc x = x := !x + 1 +fun dec x = x := !x - 1 + +val stringstart = ref 0 +val charlist = ref (nil: char list) +val lineNum = ErrorMsg.lineNum +val linePos = ErrorMsg.linePos +val comLevel = ref 0 +fun err(p1,p2) = ErrorMsg.error p1 + +val eof = fn () => + let val pos = Int.max(!stringstart+2, hd(!linePos)) + in if !comLevel>0 then err (!stringstart,pos) "unclosed comment" + else (); + Tokens.EOF(pos,pos) + end +fun addString (s:char) = charlist := s :: (!charlist) +fun makeString () = (implode(rev(!charlist)) before charlist := nil) + +fun makeInt s = + foldl (fn (c,a) => a*10 + ord c - ord #"0") 0 (explode s) + + +end (* end of user routines *) +exception LexError (* raised if illegal leaf action tried *) +structure Internal = + struct + +datatype yyfinstate = N of int +type statedata = {fin : yyfinstate list, trans: string} +(* transition & final state table *) +val tab = let +val s = [ + (0, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (1, +"\010\010\010\010\010\010\010\010\010\096\098\010\096\010\010\010\ +\\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\010\ +\\096\010\095\010\010\010\094\010\092\091\089\088\087\086\085\084\ +\\082\082\082\082\082\082\082\082\082\082\080\079\076\075\073\010\ +\\010\014\014\014\014\014\014\014\014\014\014\014\014\014\014\014\ +\\014\014\014\014\014\014\014\014\014\014\014\072\010\071\010\010\ +\\010\066\061\014\059\053\043\014\014\040\014\014\037\014\034\032\ +\\014\014\014\014\024\014\021\016\014\014\014\013\012\011\010\010\ +\\009" +), + (3, +"\099\099\099\099\099\099\099\099\099\099\104\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\102\099\100\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\099\ +\\099" +), + (5, +"\105\105\105\105\105\105\105\105\105\105\119\105\105\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105\105\118\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\106\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\105\ +\\105" +), + (7, +"\120\120\120\120\120\120\120\120\120\122\124\120\122\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\122\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\121\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\120\ +\\120" +), + (14, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (16, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\017\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (17, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\018\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (18, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\019\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (19, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\020\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (21, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\022\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (22, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\023\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (24, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\029\015\015\015\015\015\015\028\ +\\015\015\015\015\015\015\015\015\015\025\015\000\000\000\000\000\ +\\000" +), + (25, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\026\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (26, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\027\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (29, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\030\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (30, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\031\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (32, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\033\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (34, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\035\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (35, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\036\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (37, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\038\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (38, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\039\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (40, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\042\015\015\015\015\015\015\015\041\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (43, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\051\ +\\015\015\015\015\015\044\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (44, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\045\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (45, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\046\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (46, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\047\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (47, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\048\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (48, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\049\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (49, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\050\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (51, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\052\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (53, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\056\015\054\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (54, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\055\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (56, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\057\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (57, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\058\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (59, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\060\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (61, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\062\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (62, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\063\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (63, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\064\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (64, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\065\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (66, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\067\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (67, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\068\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (68, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\069\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\ +\\000" +), + (69, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\015\015\015\015\015\015\015\015\015\015\000\000\000\000\000\000\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\015\015\000\000\000\000\015\ +\\000\015\015\015\015\015\015\015\015\015\015\015\015\015\015\015\ +\\015\015\015\015\015\015\015\015\015\070\015\000\000\000\000\000\ +\\000" +), + (73, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\074\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (76, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\078\077\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (80, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\081\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (82, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\083\083\083\083\083\083\083\083\083\083\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (89, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\090\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (92, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\093\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (96, +"\000\000\000\000\000\000\000\000\000\097\000\000\097\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\097\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (100, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\101\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (102, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\103\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (106, +"\000\000\000\000\000\000\000\000\000\116\117\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\116\000\115\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\112\112\112\112\112\112\112\112\112\112\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\111\000\109\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\108\000\ +\\000\000\000\000\107\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (109, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\ +\\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\110\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (112, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\113\113\113\113\113\113\113\113\113\113\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (113, +"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\114\114\114\114\114\114\114\114\114\114\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), + (122, +"\000\000\000\000\000\000\000\000\000\123\000\000\123\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\123\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ +\\000" +), +(0, "")] +fun f x = x +val s = map f (rev (tl (rev s))) +exception LexHackingError +fun look ((j,x)::r, i) = if i = j then x else look(r, i) + | look ([], i) = raise LexHackingError +fun g {fin=x, trans=i} = {fin=x, trans=look(s,i)} +in Vector.fromList(map g +[{fin = [], trans = 0}, +{fin = [(N 2)], trans = 1}, +{fin = [(N 2)], trans = 1}, +{fin = [], trans = 3}, +{fin = [], trans = 3}, +{fin = [], trans = 5}, +{fin = [], trans = 5}, +{fin = [(N 174)], trans = 7}, +{fin = [(N 174)], trans = 7}, +{fin = [(N 147),(N 149)], trans = 0}, +{fin = [(N 149)], trans = 0}, +{fin = [(N 10),(N 149)], trans = 0}, +{fin = [(N 36),(N 149)], trans = 0}, +{fin = [(N 8),(N 149)], trans = 0}, +{fin = [(N 134),(N 149)], trans = 14}, +{fin = [(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 16}, +{fin = [(N 134)], trans = 17}, +{fin = [(N 134)], trans = 18}, +{fin = [(N 134)], trans = 19}, +{fin = [(N 64),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 21}, +{fin = [(N 134)], trans = 22}, +{fin = [(N 101),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 24}, +{fin = [(N 134)], trans = 25}, +{fin = [(N 134)], trans = 26}, +{fin = [(N 106),(N 134)], trans = 14}, +{fin = [(N 84),(N 134)], trans = 14}, +{fin = [(N 134)], trans = 29}, +{fin = [(N 134)], trans = 30}, +{fin = [(N 120),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 32}, +{fin = [(N 131),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 34}, +{fin = [(N 134)], trans = 35}, +{fin = [(N 81),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 37}, +{fin = [(N 134)], trans = 38}, +{fin = [(N 74),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 40}, +{fin = [(N 77),(N 134)], trans = 14}, +{fin = [(N 115),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 43}, +{fin = [(N 134)], trans = 44}, +{fin = [(N 134)], trans = 45}, +{fin = [(N 134)], trans = 46}, +{fin = [(N 134)], trans = 47}, +{fin = [(N 134)], trans = 48}, +{fin = [(N 134)], trans = 49}, +{fin = [(N 97),(N 134)], trans = 14}, +{fin = [(N 134)], trans = 51}, +{fin = [(N 58),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 53}, +{fin = [(N 134)], trans = 54}, +{fin = [(N 88),(N 134)], trans = 14}, +{fin = [(N 134)], trans = 56}, +{fin = [(N 134)], trans = 57}, +{fin = [(N 125),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 59}, +{fin = [(N 128),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 61}, +{fin = [(N 134)], trans = 62}, +{fin = [(N 134)], trans = 63}, +{fin = [(N 134)], trans = 64}, +{fin = [(N 70),(N 134)], trans = 14}, +{fin = [(N 134),(N 149)], trans = 66}, +{fin = [(N 134)], trans = 67}, +{fin = [(N 134)], trans = 68}, +{fin = [(N 134)], trans = 69}, +{fin = [(N 112),(N 134)], trans = 14}, +{fin = [(N 14),(N 149)], trans = 0}, +{fin = [(N 12),(N 149)], trans = 0}, +{fin = [(N 46),(N 149)], trans = 73}, +{fin = [(N 51)], trans = 0}, +{fin = [(N 41),(N 149)], trans = 0}, +{fin = [(N 48),(N 149)], trans = 76}, +{fin = [(N 44)], trans = 0}, +{fin = [(N 54)], trans = 0}, +{fin = [(N 18),(N 149)], trans = 0}, +{fin = [(N 16),(N 149)], trans = 80}, +{fin = [(N 39)], trans = 0}, +{fin = [(N 137),(N 149)], trans = 82}, +{fin = [(N 137)], trans = 82}, +{fin = [(N 32),(N 149)], trans = 0}, +{fin = [(N 24),(N 149)], trans = 0}, +{fin = [(N 28),(N 149)], trans = 0}, +{fin = [(N 6),(N 149)], trans = 0}, +{fin = [(N 26),(N 149)], trans = 0}, +{fin = [(N 30),(N 149)], trans = 89}, +{fin = [(N 145)], trans = 0}, +{fin = [(N 22),(N 149)], trans = 0}, +{fin = [(N 20),(N 149)], trans = 92}, +{fin = [(N 142)], trans = 0}, +{fin = [(N 34),(N 149)], trans = 0}, +{fin = [(N 139),(N 149)], trans = 0}, +{fin = [(N 2),(N 149)], trans = 96}, +{fin = [(N 2)], trans = 96}, +{fin = [(N 4)], trans = 0}, +{fin = [(N 159)], trans = 0}, +{fin = [(N 159)], trans = 100}, +{fin = [(N 157)], trans = 0}, +{fin = [(N 159)], trans = 102}, +{fin = [(N 152)], trans = 0}, +{fin = [(N 154)], trans = 0}, +{fin = [(N 203)], trans = 0}, +{fin = [(N 201),(N 203)], trans = 106}, +{fin = [(N 181)], trans = 0}, +{fin = [(N 184)], trans = 0}, +{fin = [], trans = 109}, +{fin = [(N 194)], trans = 0}, +{fin = [(N 187)], trans = 0}, +{fin = [], trans = 112}, +{fin = [], trans = 113}, +{fin = [(N 199)], trans = 0}, +{fin = [(N 190)], trans = 0}, +{fin = [(N 169)], trans = 0}, +{fin = [(N 166)], trans = 0}, +{fin = [(N 161),(N 203)], trans = 0}, +{fin = [(N 163)], trans = 0}, +{fin = [(N 178)], trans = 0}, +{fin = [(N 176),(N 178)], trans = 0}, +{fin = [(N 174),(N 178)], trans = 122}, +{fin = [(N 174)], trans = 122}, +{fin = [(N 171)], trans = 0}]) +end +structure StartStates = + struct + datatype yystartstate = STARTSTATE of int + +(* start state definitions *) + +val A = STARTSTATE 3; +val F = STARTSTATE 7; +val INITIAL = STARTSTATE 1; +val S = STARTSTATE 5; + +end +type result = UserDeclarations.lexresult + exception LexerError (* raised if illegal leaf action tried *) +end + +fun makeLexer yyinput = +let + val yyb = ref "\n" (* buffer *) + val yybl = ref 1 (*buffer length *) + val yybufpos = ref 1 (* location of next character to use *) + val yygone = ref 1 (* position in file of beginning of buffer *) + val yydone = ref false (* eof found yet? *) + val yybegin = ref 1 (*Current 'start state' for lexer *) + + val YYBEGIN = fn (Internal.StartStates.STARTSTATE x) => + yybegin := x + +fun lex () : Internal.result = +let fun continue() = lex() in + let fun scan (s,AcceptingLeaves : Internal.yyfinstate list list,l,i0) = + let fun action (i,nil) = raise LexError + | action (i,nil::l) = action (i-1,l) + | action (i,(node::acts)::l) = + case node of + Internal.N yyk => + (let val yytext = substring(!yyb,i0,i-i0) + val yypos = i0+ !yygone + open UserDeclarations Internal.StartStates + in (yybufpos := i; case yyk of + + (* Application actions *) + + 10 => (Tokens.RBRACE(yypos,yypos+1)) +| 101 => (Tokens.VAR(yypos,yypos+3)) +| 106 => (Tokens.TYPE(yypos,yypos+4)) +| 112 => (Tokens.ARRAY(yypos,yypos+5)) +| 115 => (Tokens.IF(yypos,yypos+2)) +| 12 => (Tokens.LBRACK(yypos,yypos+1)) +| 120 => (Tokens.THEN(yypos,yypos+4)) +| 125 => (Tokens.ELSE(yypos,yypos+4)) +| 128 => (Tokens.DO(yypos,yypos+2)) +| 131 => (Tokens.OF(yypos,yypos+2)) +| 134 => (Tokens.ID(yytext,yypos,yypos+size yytext)) +| 137 => (Tokens.INT(makeInt yytext + handle Overflow => (err (yypos,yypos+size yytext) + "integer too large"; + 1), + yypos,yypos+size yytext)) +| 139 => (charlist := nil; stringstart := yypos; + YYBEGIN S; continue()) +| 14 => (Tokens.RBRACK(yypos,yypos+1)) +| 142 => (YYBEGIN A; stringstart := yypos; comLevel := 1; continue()) +| 145 => (err (yypos,yypos+1) "unmatched close comment"; + continue()) +| 147 => (err (yypos,yypos) "non-Ascii character"; + continue()) +| 149 => (err (yypos,yypos) "illegal token"; + continue()) +| 152 => (inc comLevel; continue()) +| 154 => (inc lineNum; linePos := yypos :: !linePos; continue()) +| 157 => (dec comLevel; if !comLevel=0 then YYBEGIN INITIAL else (); continue()) +| 159 => (continue()) +| 16 => (Tokens.COLON(yypos,yypos+1)) +| 161 => (YYBEGIN INITIAL; Tokens.STRING(makeString(), + !stringstart,yypos+1)) +| 163 => (err (!stringstart,yypos) "unclosed string"; + inc lineNum; linePos := yypos :: !linePos; + YYBEGIN INITIAL; Tokens.STRING(makeString(),!stringstart,yypos)) +| 166 => (inc lineNum; linePos := yypos :: !linePos; + YYBEGIN F; continue()) +| 169 => (YYBEGIN F; continue()) +| 171 => (inc lineNum; linePos := yypos :: !linePos; continue()) +| 174 => (continue()) +| 176 => (YYBEGIN S; stringstart := yypos; continue()) +| 178 => (err (!stringstart,yypos) "unclosed string"; + YYBEGIN INITIAL; Tokens.STRING(makeString(),!stringstart,yypos+1)) +| 18 => (Tokens.SEMICOLON(yypos,yypos+1)) +| 181 => (addString #"\t"; continue()) +| 184 => (addString #"\n"; continue()) +| 187 => (addString #"\\"; continue()) +| 190 => (addString #"\""; continue()) +| 194 => (addString(chr(ord(String.sub(yytext,2))-ord(#"@"))); + continue()) +| 199 => (let val x = ord(String.sub(yytext,1))*100 + +ord(String.sub(yytext,2))*10 + +ord(String.sub(yytext,3)) + -(ord #"0" * 111) + in (if x>255 + then err (yypos,yypos+4) "illegal ascii escape" + else addString(chr x); + continue()) + end) +| 2 => (continue()) +| 20 => (Tokens.LPAREN(yypos,yypos+1)) +| 201 => (err (yypos,yypos+1) "illegal string escape"; + continue()) +| 203 => (addString(String.sub(yytext,0)); continue()) +| 22 => (Tokens.RPAREN(yypos,yypos+1)) +| 24 => (Tokens.DOT(yypos,yypos+1)) +| 26 => (Tokens.PLUS(yypos,yypos+1)) +| 28 => (Tokens.MINUS(yypos,yypos+1)) +| 30 => (Tokens.TIMES(yypos,yypos+1)) +| 32 => (Tokens.DIVIDE(yypos,yypos+1)) +| 34 => (Tokens.AND(yypos,yypos+1)) +| 36 => (Tokens.OR(yypos,yypos+1)) +| 39 => (Tokens.ASSIGN(yypos,yypos+2)) +| 4 => (inc lineNum; linePos := yypos :: !linePos; continue()) +| 41 => (Tokens.EQ(yypos,yypos+1)) +| 44 => (Tokens.NEQ(yypos,yypos+2)) +| 46 => (Tokens.GT(yypos,yypos+1)) +| 48 => (Tokens.LT(yypos,yypos+1)) +| 51 => (Tokens.GE(yypos,yypos+2)) +| 54 => (Tokens.LE(yypos,yypos+2)) +| 58 => (Tokens.FOR(yypos,yypos+3)) +| 6 => (Tokens.COMMA(yypos,yypos+1)) +| 64 => (Tokens.WHILE(yypos,yypos+5)) +| 70 => (Tokens.WHILE(yypos,yypos+5)) +| 74 => (Tokens.LET(yypos,yypos+3)) +| 77 => (Tokens.IN(yypos,yypos+2)) +| 8 => (Tokens.LBRACE(yypos,yypos+1)) +| 81 => (Tokens.NIL(yypos,yypos+3)) +| 84 => (Tokens.TO(yypos,yypos+2)) +| 88 => (Tokens.END(yypos,yypos+3)) +| 97 => (Tokens.FUNCTION(yypos,yypos+8)) +| _ => raise Internal.LexerError + + ) end ) + + val {fin,trans} = Vector.sub(Internal.tab, s) + val NewAcceptingLeaves = fin::AcceptingLeaves + in if l = !yybl then + if trans = #trans(Vector.sub(Internal.tab,0)) + then action(l,NewAcceptingLeaves +) else let val newchars= if !yydone then "" else yyinput 1024 + in if (size newchars)=0 + then (yydone := true; + if (l=i0) then UserDeclarations.eof () + else action(l,NewAcceptingLeaves)) + else (if i0=l then yyb := newchars + else yyb := substring(!yyb,i0,l-i0)^newchars; + yygone := !yygone+i0; + yybl := size (!yyb); + scan (s,AcceptingLeaves,l-i0,0)) + end + else let val NewChar = Char.ord(String.sub(!yyb,l)) + val NewState = if NewChar<128 then Char.ord(String.sub(trans,NewChar)) else Char.ord(String.sub(trans,128)) + in if NewState=0 then action(l,NewAcceptingLeaves) + else scan(NewState,NewAcceptingLeaves,l+1,i0) + end + end +(* + val start= if substring(!yyb,!yybufpos-1,1)="\n" +then !yybegin+1 else !yybegin +*) + in scan(!yybegin (* start *),nil,!yybufpos,!yybufpos) + end +end + in lex + end +end diff --git a/tiger/chap4/absyn.sml b/tiger/chap4/absyn.sml new file mode 100644 index 0000000..672f210 --- /dev/null +++ b/tiger/chap4/absyn.sml @@ -0,0 +1,52 @@ +structure Absyn = +struct + +type pos = int and symbol = Symbol.symbol + +datatype var = SimpleVar of symbol * pos + | FieldVar of var * symbol * pos + | SubscriptVar of var * exp * pos + +and exp = VarExp of var + | NilExp + | IntExp of int + | StringExp of string * pos + | CallExp of {func: symbol, args: exp list, pos: pos} + | OpExp of {left: exp, oper: oper, right: exp, pos: pos} + | RecordExp of {fields: (symbol * exp * pos) list, + typ: symbol, pos: pos} + | SeqExp of (exp * pos) list + | AssignExp of {var: var, exp: exp, pos: pos} + | IfExp of {test: exp, then': exp, else': exp option, pos: pos} + | WhileExp of {test: exp, body: exp, pos: pos} + | ForExp of {var: symbol, escape: bool ref, + lo: exp, hi: exp, body: exp, pos: pos} + | BreakExp of pos + | LetExp of {decs: dec list, body: exp, pos: pos} + | ArrayExp of {typ: symbol, size: exp, init: exp, pos: pos} + +and dec = FunctionDec of fundec list + | VarDec of {name: symbol, + escape: bool ref, + typ: (symbol * pos) option, + init: exp, + pos: pos} + | TypeDec of {name: symbol, ty: ty, pos: pos} list + +and ty = NameTy of symbol * pos + | RecordTy of field list + | ArrayTy of symbol * pos + +and oper = PlusOp | MinusOp | TimesOp | DivideOp + | EqOp | NeqOp | LtOp | LeOp | GtOp | GeOp + +withtype field = {name: symbol, escape: bool ref, + typ: symbol, pos: pos} + and fundec = {name: symbol, + params: field list, + result: (symbol * pos) option, + body: exp, + pos: pos} + +end + diff --git a/tiger/chap4/errormsg.sml b/tiger/chap4/errormsg.sml new file mode 100644 index 0000000..8a744cd --- /dev/null +++ b/tiger/chap4/errormsg.sml @@ -0,0 +1,53 @@ +signature ERRORMSG = +sig + val anyErrors : bool ref + val fileName : string ref + val lineNum : int ref + val linePos : int list ref + val sourceStream : TextIO.instream ref + val error : int -> string -> unit + exception Error + val impossible : string -> 'a (* raises Error *) + val reset : unit -> unit +end + +structure ErrorMsg : ERRORMSG = +struct + + val anyErrors = ref false + val fileName = ref "" + val lineNum = ref 1 + val linePos = ref [1] + val sourceStream = ref TextIO.stdIn + + fun reset() = (anyErrors:=false; + fileName:=""; + lineNum:=1; + linePos:=[1]; + sourceStream:=TextIO.stdIn) + + exception Error + + fun error pos (msg:string) = + let fun look(a::rest,n) = + if a Absyn.exp end = +struct + structure TigerLrVals = TigerLrValsFun(structure Token = LrParser.Token) + structure Lex = TigerLexFun(structure Tokens = TigerLrVals.Tokens) + structure TigerP = Join(structure ParserData = TigerLrVals.ParserData + structure Lex=Lex + structure LrParser = LrParser) + fun parse filename = + let val _ = (ErrorMsg.reset(); ErrorMsg.fileName := filename) + val file = TextIO.openIn filename + fun get _ = TextIO.input file + fun parseerror(s,p1,p2) = ErrorMsg.error p1 s + val lexer = LrParser.Stream.streamify (Lex.makeLexer get) + val (absyn, _) = TigerP.parse(30,lexer,parseerror,()) + in TextIO.closeIn file; + absyn + end handle LrParser.ParseError => raise ErrorMsg.Error + +end + + + diff --git a/tiger/chap4/prabsyn.sml b/tiger/chap4/prabsyn.sml new file mode 100644 index 0000000..ae9542a --- /dev/null +++ b/tiger/chap4/prabsyn.sml @@ -0,0 +1,128 @@ +structure PrintAbsyn : + sig val print : TextIO.outstream * Absyn.exp -> unit end = +struct + + structure A = Absyn + +fun print (outstream, e0) = + let fun say s = TextIO.output(outstream,s) + fun sayln s= (say s; say "\n") + + fun indent 0 = () + | indent i = (say " "; indent(i-1)) + + fun opname A.PlusOp = "PlusOp" + | opname A.MinusOp = "MinusOp" + | opname A.TimesOp = "TimesOp" + | opname A.DivideOp = "DivideOp" + | opname A.EqOp = "EqOp" + | opname A.NeqOp = "NeqOp" + | opname A.LtOp = "LtOp" + | opname A.LeOp = "LeOp" + | opname A.GtOp = "GtOp" + | opname A.GeOp = "GeOp" + + fun dolist d f [a] = (sayln ""; f(a,d+1)) + | dolist d f (a::r) = (sayln ""; f(a,d+1); say ","; dolist d f r) + | dolist d f nil = () + + + fun var(A.SimpleVar(s,p),d) = (indent d; say "SimpleVar("; + say(Symbol.name s); say ")") + | var(A.FieldVar(v,s,p),d) = (indent d; sayln "FieldVar("; + var(v,d+1); sayln ","; + indent(d+1); say(Symbol.name s); say ")") + | var(A.SubscriptVar(v,e,p),d) = (indent d; sayln "SubscriptVar("; + var(v,d+1); sayln ","; + exp(e,d+1); say ")") + and exp(A.VarExp v, d) = (indent d; sayln "VarExp("; var(v,d+1); say ")") + | exp(A.NilExp, d) = (indent d; say "NilExp") + | exp(A.IntExp i, d) = (indent d; say "IntExp("; say(Int.toString i); + say ")") + | exp(A.StringExp(s,p),d) = (indent d; say "StringExp(\""; + say s; say "\")") + | exp(A.CallExp{func,args,pos},d) = + (indent d; say "CallExp("; say(Symbol.name func); + say ",["; dolist d exp args; say "])") + | exp(A.OpExp{left,oper,right,pos},d) = + (indent d; say "OpExp("; say(opname oper); sayln ","; + exp(left,d+1); sayln ","; exp(right,d+1); say ")") + | exp(A.RecordExp{fields,typ,pos},d) = + let fun f((name,e,pos),d) = + (indent d; say "("; say(Symbol.name name); + sayln ","; exp(e,d+1); + say ")") + in indent d; say "RecordExp("; say(Symbol.name typ); + sayln ",["; dolist d f fields; say "])" + end + | exp(A.SeqExp l, d) = (indent d; say "SeqExp["; dolist d exp (map #1 l); + say "]") + | exp(A.AssignExp{var=v,exp=e,pos},d) = + (indent d; sayln "AssignExp("; var(v,d+1); sayln ","; + exp(e,d+1); say ")") + | exp(A.IfExp{test,then',else',pos},d) = + (indent d; sayln "IfExp("; exp(test,d+1); sayln ","; + exp(then',d+1); + case else' of NONE => () + | SOME e => (sayln ","; exp(e,d+1)); + say ")") + | exp(A.WhileExp{test,body,pos},d) = + (indent d; sayln "WhileExp("; exp(test,d+1); sayln ","; + exp(body,d+1); say ")") + | exp(A.ForExp{var=v,escape=b,lo,hi,body,pos},d) = + (indent d; sayln "ForExp("; + say(Symbol.name v); say ","; say(Bool.toString (!b)); sayln ","; + exp(lo,d+1); sayln ","; exp(hi,d+1); sayln ","; + exp(body,d+1); say ")") + | exp(A.BreakExp p, d) = (indent d; say "BreakExp") + | exp(A.LetExp{decs,body,pos},d) = + (indent d; say "LetExp(["; + dolist d dec decs; sayln "],"; exp(body,d+1); say")") + | exp(A.ArrayExp{typ,size,init,pos},d) = + (indent d; say "ArrayExp("; say(Symbol.name typ); sayln ","; + exp(size,d+1); sayln ","; exp(init,d+1); say ")") + + + and dec(A.FunctionDec l, d) = + let fun field({name,escape,typ,pos},d) = + (indent d; say "("; say(Symbol.name name); + say ","; say(Bool.toString(!escape)); + say ","; say(Symbol.name typ); say ")") + fun f({name,params,result,body,pos},d) = + (indent d; say "("; say (Symbol.name name); say ",["; + dolist d field params; sayln "],"; + case result of NONE => say "NONE" + | SOME(s,_) => (say "SOME("; say(Symbol.name s); say ")"); + sayln ","; exp(body,d+1); say ")") + in indent d; say "FunctionDec["; dolist d f l; say "]" + end + | dec(A.VarDec{name,escape,typ,init,pos},d) = + (indent d; say "VarDec("; say(Symbol.name name); say ","; + say(Bool.toString (!escape)); say ","; + case typ of NONE => say "NONE" + | SOME(s,p)=> (say "SOME("; say(Symbol.name s); say ")"); + sayln ","; exp(init,d+1); say ")") + | dec(A.TypeDec l, d) = + let fun tdec({name,ty=t,pos},d) = (indent d; say"("; + say(Symbol.name name); sayln ","; + ty(t,d+1); say ")") + in indent d; say "TypeDec["; dolist d tdec l; say "]" + end + + and ty(A.NameTy(s,p), d) = (indent d; say "NameTy("; say(Symbol.name s); + say ")") + | ty(A.RecordTy l, d) = + let fun f({name,escape,typ,pos},d) = + (indent d; say "("; say (Symbol.name name); + say ","; say (Bool.toString (!escape)); say ","; + say (Symbol.name typ); say ")") + in indent d; say "RecordTy["; dolist d f l; say "]" + end + | ty(A.ArrayTy(s,p),d) = (indent d; say "ArrayTy("; say(Symbol.name s); + say ")") + + in exp(e0,0); sayln ""; TextIO.flushOut outstream +end + +end + diff --git a/tiger/chap4/sources.cm b/tiger/chap4/sources.cm new file mode 100644 index 0000000..e91dfd4 --- /dev/null +++ b/tiger/chap4/sources.cm @@ -0,0 +1,13 @@ +Group is + +absyn.sml +errormsg.sml +table.sig +table.sml +symbol.sml +parse.sml +tiger.lex +tiger.grm +smlnj-lib.cm +ml-yacc-lib.cm + diff --git a/tiger/chap4/symbol.sml b/tiger/chap4/symbol.sml new file mode 100644 index 0000000..6b28228 --- /dev/null +++ b/tiger/chap4/symbol.sml @@ -0,0 +1,43 @@ +signature SYMBOL = +sig + eqtype symbol + val symbol : string -> symbol + val name : symbol -> string + type 'a table + val empty : 'a table + val enter : 'a table * symbol * 'a -> 'a table + val look : 'a table * symbol -> 'a option +end + +structure Symbol :> SYMBOL = +struct + + type symbol = string * int + + structure H = HashTable + + exception Symbol + val nextsym = ref 0 + val sizeHint = 128 + val hashtable : (string,int) H.hash_table = + H.mkTable(HashString.hashString, op = ) (sizeHint,Symbol) + + fun symbol name = + case H.find hashtable name + of SOME i => (name,i) + | NONE => let val i = !nextsym + in nextsym := i+1; + H.insert hashtable (name,i); + (name,i) + end + + fun name(s,n) = s + + structure Table = IntMapTable(type key = symbol + fun getInt(s,n) = n) + + type 'a table= 'a Table.table + val empty = Table.empty + val enter = Table.enter + val look = Table.look +end diff --git a/tiger/chap4/table.sig b/tiger/chap4/table.sig new file mode 100644 index 0000000..3ba50db --- /dev/null +++ b/tiger/chap4/table.sig @@ -0,0 +1,9 @@ +signature TABLE = +sig + type key + type 'a table + val empty : 'a table + val enter : 'a table * key * 'a -> 'a table + val look : 'a table * key -> 'a option +end + diff --git a/tiger/chap4/table.sml b/tiger/chap4/table.sml new file mode 100644 index 0000000..28ddc0e --- /dev/null +++ b/tiger/chap4/table.sml @@ -0,0 +1,9 @@ +functor IntMapTable (type key + val getInt: key -> int) : TABLE = +struct + type key=key + type 'a table = 'a IntBinaryMap.map + val empty = IntBinaryMap.empty + fun enter(t,k,a) = IntBinaryMap.insert(t,getInt k,a) + fun look(t,k) = IntBinaryMap.find(t,getInt k) +end diff --git a/tiger/chap4/tiger.grm b/tiger/chap4/tiger.grm new file mode 100644 index 0000000..2746516 --- /dev/null +++ b/tiger/chap4/tiger.grm @@ -0,0 +1,40 @@ +structure A = Absyn + +%% +%term + EOF + | ID of string + | INT of int | STRING of string + | COMMA | COLON | SEMICOLON | LPAREN | RPAREN | LBRACK | RBRACK + | LBRACE | RBRACE | DOT + | PLUS | MINUS | TIMES | DIVIDE | EQ | NEQ | LT | LE | GT | GE + | AND | OR | ASSIGN + | ARRAY | IF | THEN | ELSE | WHILE | FOR | TO | DO | LET | IN | END | OF + | BREAK | NIL + | FUNCTION | VAR | TYPE + +%nonterm exp | program of A.exp + +%pos int +%verbose +%start program +%eop EOF +%noshift EOF + +%name Tiger + +%keyword WHILE FOR TO BREAK LET IN END FUNCTION VAR TYPE ARRAY IF THEN ELSE + DO OF NIL + +%prefer THEN ELSE LPAREN + +%value ID ("bogus") +%value INT (1) +%value STRING ("") + +%% + +program : exp (exp) + + +exp: NIL (A.NilExp) diff --git a/tiger/chap5/types.sml b/tiger/chap5/types.sml new file mode 100644 index 0000000..d599187 --- /dev/null +++ b/tiger/chap5/types.sml @@ -0,0 +1,16 @@ +structure Types = +struct + + type unique = unit ref + + datatype ty = + RECORD of (Symbol.symbol * ty) list * unique + | NIL + | INT + | STRING + | ARRAY of ty * unique + | NAME of Symbol.symbol * ty option ref + | UNIT + +end + diff --git a/tiger/chap7/printtree.sml b/tiger/chap7/printtree.sml new file mode 100644 index 0000000..1337d16 --- /dev/null +++ b/tiger/chap7/printtree.sml @@ -0,0 +1,64 @@ +structure Printtree : + sig val printtree : TextIO.outstream * Tree.stm -> unit end = +struct + + structure T = Tree +fun printtree (outstream, s0) = + let fun say s = TextIO.output(outstream,s) + fun sayln s= (say s; say "\n") + + fun indent 0 = () + | indent i = (say " "; indent(i-1)) + + fun stm(T.SEQ(a,b),d) = + (indent d; sayln "SEQ("; stm(a,d+1); sayln ","; stm(b,d+1); say ")") + | stm(T.LABEL lab, d) = (indent d; say "LABEL "; say (Symbol.name lab)) + | stm(T.JUMP (e,_), d) = (indent d; sayln "JUMP("; exp(e,d+1); say ")") + | stm(T.CJUMP(r,a,b,t,f),d) = (indent d; say "CJUMP("; + relop r; sayln ","; + exp(a,d+1); sayln ","; exp(b,d+1); sayln ","; + indent(d+1); say(Symbol.name t); + say ","; say (Symbol.name f); say ")") + | stm(T.MOVE(a,b),d) = (indent d; sayln "MOVE("; exp(a,d+1); sayln ","; + exp(b,d+1); say ")") + | stm(T.EXP e, d) = (indent d; sayln "EXP("; exp(e,d+1); say ")") + + and exp(T.BINOP(p,a,b),d) = (indent d; say "BINOP("; binop p; sayln ","; + exp(a,d+1); sayln ","; exp(b,d+1); say ")") + | exp(T.MEM(e),d) = (indent d; sayln "MEM("; exp(e,d+1); say ")") + | exp(T.TEMP t, d) = (indent d; say "TEMP t"; say(Int.toString t)) + | exp(T.ESEQ(s,e),d) = (indent d; sayln "ESEQ("; stm(s,d+1); sayln ","; + exp(e,d+1); say ")") + | exp(T.NAME lab, d) = (indent d; say "NAME "; say (Symbol.name lab)) + | exp(T.CONST i, d) = (indent d; say "CONST "; say(Int.toString i)) + | exp(T.CALL(e,el),d) = (indent d; sayln "CALL("; exp(e,d+1); + app (fn a => (sayln ","; exp(a,d+2))) el; + say ")") + + and binop T.PLUS = say "PLUS" + | binop T.MINUS = say "MINUS" + | binop T.MUL = say "MUL" + | binop T.DIV = say "DIV" + | binop T.AND = say "AND" + | binop T.OR = say "OR" + | binop T.LSHIFT = say "LSHIFT" + | binop T.RSHIFT = say "RSHIFT" + | binop T.ARSHIFT = say "ARSHIFT" + | binop T.XOR = say "XOR" + + and relop T.EQ = say "EQ" + | relop T.NE = say "NE" + | relop T.LT = say "LT" + | relop T.GT = say "GT" + | relop T.LE = say "LE" + | relop T.GE = say "GE" + | relop T.ULT = say "ULT" + | relop T.ULE = say "ULE" + | relop T.UGT = say "UGT" + | relop T.UGE = say "UGE" + + in stm(s0,0); sayln ""; TextIO.flushOut outstream +end + +end + diff --git a/tiger/chap7/temp.sig b/tiger/chap7/temp.sig new file mode 100644 index 0000000..700376c --- /dev/null +++ b/tiger/chap7/temp.sig @@ -0,0 +1,11 @@ +signature TEMP = +sig + eqtype temp + val newtemp : unit -> temp + structure Table : TABLE sharing type Table.key = temp + val makestring: temp -> string + type label = Symbol.symbol + val newlabel : unit -> label + val namedlabel : string -> label +end + diff --git a/tiger/chap7/temp.sml b/tiger/chap7/temp.sml new file mode 100644 index 0000000..9b72d8b --- /dev/null +++ b/tiger/chap7/temp.sml @@ -0,0 +1,24 @@ +(* make this an abstraction sometime *) +structure Temp : TEMP = +struct + type temp = int + val temps = ref 100 + fun newtemp() = let val t = !temps in temps := t+1; t end + + structure Table = IntMapTable(type key = int + fun getInt n = n) + + fun makestring t = "t" ^ Int.toString t + + type label = Symbol.symbol + +local structure F = Format + fun postinc x = let val i = !x in x := i+1; i end + val labs = ref 0 + in + fun newlabel() = Symbol.symbol(F.format "L%d" [F.INT(postinc labs)]) + val namedlabel = Symbol.symbol +end + + +end diff --git a/tiger/chap7/tree.sml b/tiger/chap7/tree.sml new file mode 100644 index 0000000..830c4da --- /dev/null +++ b/tiger/chap7/tree.sml @@ -0,0 +1,58 @@ +signature TREE = +sig + type label = Temp.label + type size + +datatype stm = SEQ of stm * stm + | LABEL of label + | JUMP of exp * label list + | CJUMP of relop * exp * exp * label * label + | MOVE of exp * exp + | EXP of exp + + and exp = BINOP of binop * exp * exp + | MEM of exp + | TEMP of Temp.temp + | ESEQ of stm * exp + | NAME of label + | CONST of int + | CALL of exp * exp list + + and binop = PLUS | MINUS | MUL | DIV + | AND | OR | LSHIFT | RSHIFT | ARSHIFT | XOR + + and relop = EQ | NE | LT | GT | LE | GE + | ULT | ULE | UGT | UGE + + val notRel : relop -> relop + val commute: relop -> relop +end + +structure Tree : TREE = +struct + type label=Temp.label + type size = int + +datatype stm = SEQ of stm * stm + | LABEL of label + | JUMP of exp * label list + | CJUMP of relop * exp * exp * label * label + | MOVE of exp * exp + | EXP of exp + + and exp = BINOP of binop * exp * exp + | MEM of exp + | TEMP of Temp.temp + | ESEQ of stm * exp + | NAME of label + | CONST of int + | CALL of exp * exp list + + and binop = PLUS | MINUS | MUL | DIV + | AND | OR | LSHIFT | RSHIFT | ARSHIFT | XOR + + and relop = EQ | NE | LT | GT | LE | GE + | ULT | ULE | UGT | UGE + +end + diff --git a/tiger/chap8/canon.sml b/tiger/chap8/canon.sml new file mode 100644 index 0000000..7e0ea9c --- /dev/null +++ b/tiger/chap8/canon.sml @@ -0,0 +1,183 @@ +signature CANON = +sig + val linearize : Tree.stm -> Tree.stm list + (* From an arbitrary Tree statement, produce a list of cleaned trees + satisfying the following properties: + 1. No SEQ's or ESEQ's + 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) + *) + + val basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) + (* From a list of cleaned trees, produce a list of + basic blocks satisfying the following properties: + 1. and 2. as above; + 3. Every block begins with a LABEL; + 4. A LABEL appears only at the beginning of a block; + 5. Any JUMP or CJUMP is the last stm in a block; + 6. Every block ends with a JUMP or CJUMP; + Also produce the "label" to which control will be passed + upon exit. + *) + + val traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list + (* From a list of basic blocks satisfying properties 1-6, + along with an "exit" label, + produce a list of stms such that: + 1. and 2. as above; + 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. + The blocks are reordered to satisfy property 7; also + in this reordering as many JUMP(T.NAME(lab)) statements + as possible are eliminated by falling through into T.LABEL(lab). + *) +end + +structure Canon : CANON = +struct + + structure T = Tree + + fun linearize(stm0: T.stm) : T.stm list = + let + infix % + fun (T.EXP(T.CONST _)) % x = x + | x % (T.EXP(T.CONST _)) = x + | x % y = T.SEQ(x,y) + + fun commute(T.EXP(T.CONST _), _) = true + | commute(_, T.NAME _) = true + | commute(_, T.CONST _) = true + | commute _ = false + + val nop = T.EXP(T.CONST 0) + + fun reorder ((e as T.CALL _ )::rest) = + let val t = Temp.newtemp() + in reorder(T.ESEQ(T.MOVE(T.TEMP t, e), T.TEMP t) :: rest) + end + | reorder (a::rest) = + let val (stms,e) = do_exp a + val (stms',el) = reorder rest + in if commute(stms',e) + then (stms % stms',e::el) + else let val t = Temp.newtemp() + in (stms % T.MOVE(T.TEMP t, e) % stms', T.TEMP t :: el) + end + end + | reorder nil = (nop,nil) + + and reorder_exp(el,build) = let val (stms,el') = reorder el + in (stms, build el') + end + + and reorder_stm(el,build) = let val (stms,el') = reorder (el) + in stms % build(el') + end + + and do_stm(T.SEQ(a,b)) = + do_stm a % do_stm b + | do_stm(T.JUMP(e,labs)) = + reorder_stm([e],fn [e] => T.JUMP(e,labs)) + | do_stm(T.CJUMP(p,a,b,t,f)) = + reorder_stm([a,b], fn[a,b]=> T.CJUMP(p,a,b,t,f)) + | do_stm(T.MOVE(T.TEMP t,T.CALL(e,el))) = + reorder_stm(e::el,fn e::el => T.MOVE(T.TEMP t,T.CALL(e,el))) + | do_stm(T.MOVE(T.TEMP t,b)) = + reorder_stm([b],fn[b]=>T.MOVE(T.TEMP t,b)) + | do_stm(T.MOVE(T.MEM e,b)) = + reorder_stm([e,b],fn[e,b]=>T.MOVE(T.MEM e,b)) + | do_stm(T.MOVE(T.ESEQ(s,e),b)) = + do_stm(T.SEQ(s,T.MOVE(e,b))) + | do_stm(T.EXP(T.CALL(e,el))) = + reorder_stm(e::el,fn e::el => T.EXP(T.CALL(e,el))) + | do_stm(T.EXP e) = + reorder_stm([e],fn[e]=>T.EXP e) + | do_stm s = reorder_stm([],fn[]=>s) + + and do_exp(T.BINOP(p,a,b)) = + reorder_exp([a,b], fn[a,b]=>T.BINOP(p,a,b)) + | do_exp(T.MEM(a)) = + reorder_exp([a], fn[a]=>T.MEM(a)) + | do_exp(T.ESEQ(s,e)) = + let val stms = do_stm s + val (stms',e) = do_exp e + in (stms%stms',e) + end + | do_exp(T.CALL(e,el)) = + reorder_exp(e::el, fn e::el => T.CALL(e,el)) + | do_exp e = reorder_exp([],fn[]=>e) + + (* linear gets rid of the top-level SEQ's, producing a list *) + fun linear(T.SEQ(a,b),l) = linear(a,linear(b,l)) + | linear(s,l) = s::l + + in (* body of linearize *) + linear(do_stm stm0, nil) + end + + type block = T.stm list + + (* Take list of statements and make basic blocks satisfying conditions + 3 and 4 above, in addition to the extra condition that + every block ends with a JUMP or CJUMP *) + + fun basicBlocks stms = + let val done = Temp.newlabel() + fun blocks((head as T.LABEL _) :: tail, blist) = + let fun next((s as (T.JUMP _))::rest, thisblock) = + endblock(rest, s::thisblock) + | next((s as (T.CJUMP _))::rest, thisblock) = + endblock(rest,s::thisblock) + | next(stms as (T.LABEL lab :: _), thisblock) = + next(T.JUMP(T.NAME lab,[lab]) :: stms, thisblock) + | next(s::rest, thisblock) = next(rest, s::thisblock) + | next(nil, thisblock) = + next([T.JUMP(T.NAME done, [done])], thisblock) + + and endblock(stms, thisblock) = + blocks(stms, rev thisblock :: blist) + + in next(tail, [head]) + end + | blocks(nil, blist) = rev blist + | blocks(stms, blist) = blocks(T.LABEL(Temp.newlabel())::stms, blist) + in (blocks(stms,nil), done) + end + + fun enterblock(b as (T.LABEL s :: _), table) = Symbol.enter(table,s,b) + | enterblock(_, table) = table + + fun splitlast([x]) = (nil,x) + | splitlast(h::t) = let val (t',last) = splitlast t in (h::t', last) end + + fun trace(table,b as (T.LABEL lab :: _),rest) = + let val table = Symbol.enter(table, lab, nil) + in case splitlast b + of (most,T.JUMP(T.NAME lab, _)) => + (case Symbol.look(table, lab) + of SOME(b' as _::_) => most @ trace(table, b', rest) + | _ => b @ getnext(table,rest)) + | (most,T.CJUMP(opr,x,y,t,f)) => + (case (Symbol.look(table,t), Symbol.look(table,f)) + of (_, SOME(b' as _::_)) => b @ trace(table, b', rest) + | (SOME(b' as _::_), _) => + most @ [T.CJUMP(T.notRel opr,x,y,f,t)] + @ trace(table, b', rest) + | _ => let val f' = Temp.newlabel() + in most @ [T.CJUMP(opr,x,y,t,f'), + T.LABEL f', T.JUMP(T.NAME f,[f])] + @ getnext(table,rest) + end) + | (most, T.JUMP _) => b @ getnext(table,rest) + end + + and getnext(table,(b as (T.LABEL lab::_))::rest) = + (case Symbol.look(table, lab) + of SOME(_::_) => trace(table,b,rest) + | _ => getnext(table,rest)) + | getnext(table,nil) = nil + + fun traceSchedule(blocks,done) = + getnext(foldr enterblock Symbol.empty blocks, blocks) + @ [T.LABEL done] + +end diff --git a/tiger/chap9/assem.sml b/tiger/chap9/assem.sml new file mode 100644 index 0000000..b46a7d4 --- /dev/null +++ b/tiger/chap9/assem.sml @@ -0,0 +1,39 @@ +structure Assem = struct + + type reg = string + type temp = Temp.temp + type label = Temp.label + + datatype instr = OPER of {assem: string, + dst: temp list, + src: temp list, + jump: label list option} + | LABEL of {assem: string, lab: Temp.label} + | MOVE of {assem: string, + dst: temp, + src: temp} + + fun format saytemp = + let + fun speak(assem,dst,src,jump) = + let val saylab = Symbol.name + fun f(#"`":: #"s":: i::rest) = + (explode(saytemp(List.nth(src,ord i - ord #"0"))) @ f rest) + | f( #"`":: #"d":: i:: rest) = + (explode(saytemp(List.nth(dst,ord i - ord #"0"))) @ f rest) + | f( #"`":: #"j":: i:: rest) = + (explode(saylab(List.nth(jump,ord i - ord #"0"))) @ f rest) + | f( #"`":: #"`":: rest) = #"`" :: f rest + | f( #"`":: _ :: rest) = ErrorMsg.impossible "bad Assem format" + | f(c :: rest) = (c :: f rest) + | f nil = nil + in implode(f(explode assem)) + end + in fn OPER{assem,dst,src,jump=NONE} => speak(assem,dst,src,nil) + | OPER{assem,dst,src,jump=SOME j} => speak(assem,dst,src,j) + | LABEL{assem,...} => assem + | MOVE{assem,dst,src} => speak(assem,[dst],[src],nil) + end + +end + diff --git a/tiger/chap9/canon.sml b/tiger/chap9/canon.sml new file mode 100644 index 0000000..7e0ea9c --- /dev/null +++ b/tiger/chap9/canon.sml @@ -0,0 +1,183 @@ +signature CANON = +sig + val linearize : Tree.stm -> Tree.stm list + (* From an arbitrary Tree statement, produce a list of cleaned trees + satisfying the following properties: + 1. No SEQ's or ESEQ's + 2. The parent of every CALL is an EXP(..) or a MOVE(TEMP t,..) + *) + + val basicBlocks : Tree.stm list -> (Tree.stm list list * Tree.label) + (* From a list of cleaned trees, produce a list of + basic blocks satisfying the following properties: + 1. and 2. as above; + 3. Every block begins with a LABEL; + 4. A LABEL appears only at the beginning of a block; + 5. Any JUMP or CJUMP is the last stm in a block; + 6. Every block ends with a JUMP or CJUMP; + Also produce the "label" to which control will be passed + upon exit. + *) + + val traceSchedule : Tree.stm list list * Tree.label -> Tree.stm list + (* From a list of basic blocks satisfying properties 1-6, + along with an "exit" label, + produce a list of stms such that: + 1. and 2. as above; + 7. Every CJUMP(_,t,f) is immediately followed by LABEL f. + The blocks are reordered to satisfy property 7; also + in this reordering as many JUMP(T.NAME(lab)) statements + as possible are eliminated by falling through into T.LABEL(lab). + *) +end + +structure Canon : CANON = +struct + + structure T = Tree + + fun linearize(stm0: T.stm) : T.stm list = + let + infix % + fun (T.EXP(T.CONST _)) % x = x + | x % (T.EXP(T.CONST _)) = x + | x % y = T.SEQ(x,y) + + fun commute(T.EXP(T.CONST _), _) = true + | commute(_, T.NAME _) = true + | commute(_, T.CONST _) = true + | commute _ = false + + val nop = T.EXP(T.CONST 0) + + fun reorder ((e as T.CALL _ )::rest) = + let val t = Temp.newtemp() + in reorder(T.ESEQ(T.MOVE(T.TEMP t, e), T.TEMP t) :: rest) + end + | reorder (a::rest) = + let val (stms,e) = do_exp a + val (stms',el) = reorder rest + in if commute(stms',e) + then (stms % stms',e::el) + else let val t = Temp.newtemp() + in (stms % T.MOVE(T.TEMP t, e) % stms', T.TEMP t :: el) + end + end + | reorder nil = (nop,nil) + + and reorder_exp(el,build) = let val (stms,el') = reorder el + in (stms, build el') + end + + and reorder_stm(el,build) = let val (stms,el') = reorder (el) + in stms % build(el') + end + + and do_stm(T.SEQ(a,b)) = + do_stm a % do_stm b + | do_stm(T.JUMP(e,labs)) = + reorder_stm([e],fn [e] => T.JUMP(e,labs)) + | do_stm(T.CJUMP(p,a,b,t,f)) = + reorder_stm([a,b], fn[a,b]=> T.CJUMP(p,a,b,t,f)) + | do_stm(T.MOVE(T.TEMP t,T.CALL(e,el))) = + reorder_stm(e::el,fn e::el => T.MOVE(T.TEMP t,T.CALL(e,el))) + | do_stm(T.MOVE(T.TEMP t,b)) = + reorder_stm([b],fn[b]=>T.MOVE(T.TEMP t,b)) + | do_stm(T.MOVE(T.MEM e,b)) = + reorder_stm([e,b],fn[e,b]=>T.MOVE(T.MEM e,b)) + | do_stm(T.MOVE(T.ESEQ(s,e),b)) = + do_stm(T.SEQ(s,T.MOVE(e,b))) + | do_stm(T.EXP(T.CALL(e,el))) = + reorder_stm(e::el,fn e::el => T.EXP(T.CALL(e,el))) + | do_stm(T.EXP e) = + reorder_stm([e],fn[e]=>T.EXP e) + | do_stm s = reorder_stm([],fn[]=>s) + + and do_exp(T.BINOP(p,a,b)) = + reorder_exp([a,b], fn[a,b]=>T.BINOP(p,a,b)) + | do_exp(T.MEM(a)) = + reorder_exp([a], fn[a]=>T.MEM(a)) + | do_exp(T.ESEQ(s,e)) = + let val stms = do_stm s + val (stms',e) = do_exp e + in (stms%stms',e) + end + | do_exp(T.CALL(e,el)) = + reorder_exp(e::el, fn e::el => T.CALL(e,el)) + | do_exp e = reorder_exp([],fn[]=>e) + + (* linear gets rid of the top-level SEQ's, producing a list *) + fun linear(T.SEQ(a,b),l) = linear(a,linear(b,l)) + | linear(s,l) = s::l + + in (* body of linearize *) + linear(do_stm stm0, nil) + end + + type block = T.stm list + + (* Take list of statements and make basic blocks satisfying conditions + 3 and 4 above, in addition to the extra condition that + every block ends with a JUMP or CJUMP *) + + fun basicBlocks stms = + let val done = Temp.newlabel() + fun blocks((head as T.LABEL _) :: tail, blist) = + let fun next((s as (T.JUMP _))::rest, thisblock) = + endblock(rest, s::thisblock) + | next((s as (T.CJUMP _))::rest, thisblock) = + endblock(rest,s::thisblock) + | next(stms as (T.LABEL lab :: _), thisblock) = + next(T.JUMP(T.NAME lab,[lab]) :: stms, thisblock) + | next(s::rest, thisblock) = next(rest, s::thisblock) + | next(nil, thisblock) = + next([T.JUMP(T.NAME done, [done])], thisblock) + + and endblock(stms, thisblock) = + blocks(stms, rev thisblock :: blist) + + in next(tail, [head]) + end + | blocks(nil, blist) = rev blist + | blocks(stms, blist) = blocks(T.LABEL(Temp.newlabel())::stms, blist) + in (blocks(stms,nil), done) + end + + fun enterblock(b as (T.LABEL s :: _), table) = Symbol.enter(table,s,b) + | enterblock(_, table) = table + + fun splitlast([x]) = (nil,x) + | splitlast(h::t) = let val (t',last) = splitlast t in (h::t', last) end + + fun trace(table,b as (T.LABEL lab :: _),rest) = + let val table = Symbol.enter(table, lab, nil) + in case splitlast b + of (most,T.JUMP(T.NAME lab, _)) => + (case Symbol.look(table, lab) + of SOME(b' as _::_) => most @ trace(table, b', rest) + | _ => b @ getnext(table,rest)) + | (most,T.CJUMP(opr,x,y,t,f)) => + (case (Symbol.look(table,t), Symbol.look(table,f)) + of (_, SOME(b' as _::_)) => b @ trace(table, b', rest) + | (SOME(b' as _::_), _) => + most @ [T.CJUMP(T.notRel opr,x,y,f,t)] + @ trace(table, b', rest) + | _ => let val f' = Temp.newlabel() + in most @ [T.CJUMP(opr,x,y,t,f'), + T.LABEL f', T.JUMP(T.NAME f,[f])] + @ getnext(table,rest) + end) + | (most, T.JUMP _) => b @ getnext(table,rest) + end + + and getnext(table,(b as (T.LABEL lab::_))::rest) = + (case Symbol.look(table, lab) + of SOME(_::_) => trace(table,b,rest) + | _ => getnext(table,rest)) + | getnext(table,nil) = nil + + fun traceSchedule(blocks,done) = + getnext(foldr enterblock Symbol.empty blocks, blocks) + @ [T.LABEL done] + +end diff --git a/tiger/chap9/flowgraph.sml b/tiger/chap9/flowgraph.sml new file mode 100644 index 0000000..f427102 --- /dev/null +++ b/tiger/chap9/flowgraph.sml @@ -0,0 +1,23 @@ +structure Flow = +struct + datatype flowgraph = FGRAPH of {control: Graph.graph, + def: Temp.temp list Graph.Table.table, + use: Temp.temp list Graph.Table.table, + ismove: bool Graph.Table.table} + + (* Note: any "use" within the block is assumed to be BEFORE a "def" + of the same variable. If there is a def(x) followed by use(x) + in the same block, do not mention the use in this data structure, + mention only the def. + + More generally: + If there are any nonzero number of defs, mention def(x). + If there are any nonzero number of uses BEFORE THE FIRST DEF, + mention use(x). + + For any node in the graph, + Graph.Table.look(def,node) = SOME(def-list) + Graph.Table.look(use,node) = SOME(use-list) + *) + +end diff --git a/tiger/chap9/graph.sig b/tiger/chap9/graph.sig new file mode 100644 index 0000000..51db896 --- /dev/null +++ b/tiger/chap9/graph.sig @@ -0,0 +1,23 @@ +signature GRAPH = +sig + type graph + type node + + val nodes: graph -> node list + val succ: node -> node list + val pred: node -> node list + val adj: node -> node list (* succ+pred *) + val eq: node*node -> bool + + val newGraph: unit -> graph + val newNode : graph -> node + exception GraphEdge + val mk_edge: {from: node, to: node} -> unit + val rm_edge: {from: node, to: node} -> unit + + structure Table : TABLE + sharing type Table.key = node + + val nodename: node->string (* for debugging only *) + +end diff --git a/tiger/chap9/graph.sml b/tiger/chap9/graph.sml new file mode 100644 index 0000000..a2b6d5c --- /dev/null +++ b/tiger/chap9/graph.sml @@ -0,0 +1,80 @@ +structure Graph :> GRAPH = +struct + type node' = int + type temp = Temp.temp + + datatype noderep = NODE of {succ: node' list, pred: node' list} + + val emptyNode = NODE{succ=[],pred=[]} + + val bogusNode = NODE{succ=[~1],pred=[]} + + fun isBogus(NODE{succ= ~1::_,...}) = true + | isBogus _ = false + + structure A = DynamicArrayFn(struct open Array + type elem = noderep + type vector = noderep vector + type array = noderep array + end) + + type graph = A.array + + type node = graph * node' + fun eq((_,a),(_,b)) = a=b + + fun augment (g: graph) (n: node') : node = (g,n) + + fun newGraph() = A.array(0,bogusNode) + + fun nodes g = let val b = A.bound g + fun f i = if isBogus( A.sub(g,i)) then nil + else (g,i)::f(i+1) + in f 0 + end + + fun succ(g,i) = let val NODE{succ=s,...} = A.sub(g,i) + in map (augment g) s + end + fun pred(g,i) = let val NODE{pred=p,...} = A.sub(g,i) + in map (augment g) p + end + fun adj gi = pred gi @ succ gi + + fun newNode g = (* binary search for unused node *) + let fun look(lo,hi) = + (* i < lo indicates i in use + i >= hi indicates i not in use *) + if lo=hi then (A.update(g,lo,emptyNode); (g,lo)) + else let val m = (lo+hi) div 2 + in if isBogus(A.sub(g,m)) then look(lo,m) else look(m+1,hi) + end + in look(0, 1 + A.bound g) + end + + exception GraphEdge + fun check(g,g') = (* if g=g' then () else raise GraphEdge *) () + + fun delete(i,j::rest) = if i=j then rest else j::delete(i,rest) + | delete(_,nil) = raise GraphEdge + + fun diddle_edge change {from=(g:graph, i),to=(g':graph, j)} = + let val _ = check(g,g') + val NODE{succ=si,pred=pi} = A.sub(g,i) + val _ = A.update(g,i,NODE{succ=change(j,si),pred=pi}) + val NODE{succ=sj,pred=pj} = A.sub(g,j) + val _ = A.update(g,j,NODE{succ=sj,pred=change(i,pj)}) + in () + end + + val mk_edge = diddle_edge (op ::) + val rm_edge = diddle_edge delete + + structure Table = IntMapTable(type key = node + fun getInt(g,n) = n) + + + fun nodename(g,i:int) = "n" ^ Int.toString(i) + +end + diff --git a/tiger/chap9/main.sml b/tiger/chap9/main.sml new file mode 100644 index 0000000..75532d7 --- /dev/null +++ b/tiger/chap9/main.sml @@ -0,0 +1,39 @@ +structure Main = struct + + structure Tr = Translate + structure F = Frame + structure R = RegAlloc + + fun getsome (SOME x) = x + + fun emitproc out (F.PROC{body,frame}) = + let val _ = print ("emit " ^ Frame.name frame ^ "\n") +(* val _ = Printtree.printtree(out,body); *) + val stms = Canon.linearize body +(* val _ = app (fn s => Printtree.printtree(out,s)) stms; *) + val stms' = Canon.traceSchedule(Canon.basicBlocks stms) + val instrs = List.concat(map (Mips.codegen frame) stms') + val format0 = Assem.format(Temp.makestring) + in app (fn i => TextIO.output(out,format0 i)) instrs; + end + end + | emitproc out (F.STRING(lab,s)) = TextIO.output(out,F.string(lab,s)) + + fun withOpenFile fname f = + let val out = TextIO.openOut fname + in (f out before TextIO.closeOut out) + handle e => (TextIO.closeOut out; raise e) + end + + fun compile filename = + let val absyn = Parse.parse filename + val frags = (FindEscape.prog absyn; Semant.transProg absyn) + in + withOpenFile (filename ^ ".s") + (fn out => (app (emitproc out) frags)) + end + +end + + + diff --git a/tiger/chap9/runtime.c b/tiger/chap9/runtime.c new file mode 100644 index 0000000..106ad56 --- /dev/null +++ b/tiger/chap9/runtime.c @@ -0,0 +1,109 @@ +#undef __STDC__ +#include + + +int *initArray(int size, int init) +{int i; + int *a = (int *)malloc(size*sizeof(int)); + for(i=0;ilength!=t->length) return 0; + for(i=0;ilength;i++) if (s->chars[i]!=t->chars[i]) return 0; + return 1; +} + +void print(struct string *s) +{int i; unsigned char *p=s->chars; + for(i=0;ilength;i++,p++) putchar(*p); +} + +void flush() +{ + fflush(stdout); +} + +struct string consts[256]; +struct string empty={0,""}; + +int main() +{int i; + for(i=0;i<256;i++) + {consts[i].length=1; + consts[i].chars[0]=i; + } + return tigermain(0 /* static link!? */); +} + +int ord(struct string *s) +{ + if (s->length==0) return -1; + else return s->chars[0]; +} + +struct string *chr(int i) +{ + if (i<0 || i>=256) + {printf("chr(%d) out of range\n",i); exit(1);} + return consts+i; +} + +int size(struct string *s) +{ + return s->length; +} + +struct string *substring(struct string *s, int first, int n) +{ + if (first<0 || first+n>s->length) + {printf("substring([%d],%d,%d) out of range\n",s->length,first,n); + exit(1);} + if (n==1) return consts+s->chars[first]; + {struct string *t = (struct string *)malloc(sizeof(int)+n); + int i; + t->length=n; + for(i=0;ichars[i]=s->chars[first+i]; + return t; + } +} + +struct string *concat(struct string *a, struct string *b) +{ + if (a->length==0) return b; + else if (b->length==0) return a; + else {int i, n=a->length+b->length; + struct string *t = (struct string *)malloc(sizeof(int)+n); + t->length=n; + for (i=0;ilength;i++) + t->chars[i]=a->chars[i]; + for(i=0;ilength;i++) + t->chars[i+a->length]=b->chars[i]; + return t; + } +} + +int not(int i) +{ return !i; +} + +#undef getchar + +struct string *getchar() +{int i=getc(stdin); + if (i==EOF) return ∅ + else return consts+i; +} diff --git a/tiger/testcases/merge.tig b/tiger/testcases/merge.tig new file mode 100644 index 0000000..02b215a --- /dev/null +++ b/tiger/testcases/merge.tig @@ -0,0 +1,56 @@ +let + + type any = {any : int} + var buffer := getchar() + +function readint(any: any) : int = + let var i := 0 + function isdigit(s : string) : int = + ord(buffer)>=ord("0") & ord(buffer)<=ord("9") + function skipto() = + while buffer=" " | buffer="\n" + do buffer := getchar() + in skipto(); + any.any := isdigit(buffer); + while isdigit(buffer) + do (i := i*10+ord(buffer)-ord("0"); buffer := getchar()); + i + end + + type list = {first: int, rest: list} + + function readlist() : list = + let var any := any{any=0} + var i := readint(any) + in if any.any + then list{first=i,rest=readlist()} + else nil + end + + function merge(a: list, b: list) : list = + if a=nil then b + else if b=nil then a + else if a.first < b.first + then list{first=a.first,rest=merge(a.rest,b)} + else list{first=b.first,rest=merge(a,b.rest)} + + function printint(i: int) = + let function f(i:int) = if i>0 + then (f(i/10); print(chr(i-i/10*10+ord("0")))) + in if i<0 then (print("-"); f(-i)) + else if i>0 then f(i) + else print("0") + end + + function printlist(l: list) = + if l=nil then print("\n") + else (printint(l.first); print(" "); printlist(l.rest)) + + var list1 := readlist() + var list2 := (buffer:=getchar(); readlist()) + + + /* BODY OF MAIN PROGRAM */ + in printlist(merge(list1,list2)) +end + diff --git a/tiger/testcases/queens.tig b/tiger/testcases/queens.tig new file mode 100644 index 0000000..0c3b126 --- /dev/null +++ b/tiger/testcases/queens.tig @@ -0,0 +1,34 @@ +/* A program to solve the 8-queens problem */ + +let + var N := 8 + + type intArray = array of int + + var row := intArray [ N ] of 0 + var col := intArray [ N ] of 0 + var diag1 := intArray [N+N-1] of 0 + var diag2 := intArray [N+N-1] of 0 + + function printboard() = + (for i := 0 to N-1 + do (for j := 0 to N-1 + do print(if col[i]=j then " O" else " ."); + print("\n")); + print("\n")) + + function try(c:int) = +( /* for i:= 0 to c do print("."); print("\n"); flush();*/ + if c=N + then printboard() + else for r := 0 to N-1 + do if row[r]=0 & diag1[r+c]=0 & diag2[r+7-c]=0 + then (row[r]:=1; diag1[r+c]:=1; diag2[r+7-c]:=1; + col[c]:=r; + try(c+1); + row[r]:=0; diag1[r+c]:=0; diag2[r+7-c]:=0) + +) + in try(0) +end + \ No newline at end of file diff --git a/tiger/testcases/test1.tig b/tiger/testcases/test1.tig new file mode 100644 index 0000000..6ce6952 --- /dev/null +++ b/tiger/testcases/test1.tig @@ -0,0 +1,7 @@ +/* an array type and an array variable */ +let + type arrtype = array of int + var arr1:arrtype := arrtype [10] of 0 +in + arr1 +end diff --git a/tiger/testcases/test10.tig b/tiger/testcases/test10.tig new file mode 100644 index 0000000..d4038d7 --- /dev/null +++ b/tiger/testcases/test10.tig @@ -0,0 +1,2 @@ +/* error : body of while not unit */ +while(10 > 5) do 5+6 diff --git a/tiger/testcases/test11.tig b/tiger/testcases/test11.tig new file mode 100644 index 0000000..6e53126 --- /dev/null +++ b/tiger/testcases/test11.tig @@ -0,0 +1,3 @@ +/* error hi expr is not int, and index variable erroneously assigned to. */ +for i:=10 to " " do + i := i - 1 diff --git a/tiger/testcases/test12.tig b/tiger/testcases/test12.tig new file mode 100644 index 0000000..950d1ad --- /dev/null +++ b/tiger/testcases/test12.tig @@ -0,0 +1,7 @@ +/* valid for and let */ + +let + var a:= 0 +in + for i:=0 to 100 do (a:=a+1;()) +end diff --git a/tiger/testcases/test13.tig b/tiger/testcases/test13.tig new file mode 100644 index 0000000..5491c6c --- /dev/null +++ b/tiger/testcases/test13.tig @@ -0,0 +1,3 @@ +/* error: comparison of incompatible types */ + +3 > "df" diff --git a/tiger/testcases/test14.tig b/tiger/testcases/test14.tig new file mode 100644 index 0000000..9c4a7e0 --- /dev/null +++ b/tiger/testcases/test14.tig @@ -0,0 +1,13 @@ +/* error : compare rec with array */ + +let + + type arrtype = array of int + type rectype = {name:string, id: int} + + var rec := rectype {name="aname", id=0} + var arr := arrtype [3] of 0 + +in + if rec <> arr then 3 else 4 +end diff --git a/tiger/testcases/test15.tig b/tiger/testcases/test15.tig new file mode 100644 index 0000000..1af763e --- /dev/null +++ b/tiger/testcases/test15.tig @@ -0,0 +1,3 @@ +/* error : if-then returns non unit */ + +if 20 then 3 diff --git a/tiger/testcases/test16.tig b/tiger/testcases/test16.tig new file mode 100644 index 0000000..8ff97b1 --- /dev/null +++ b/tiger/testcases/test16.tig @@ -0,0 +1,11 @@ +/* error: mutually recursive types thet do not pass through record or array */ +let + +type a=c +type b=a +type c=d +type d=a + +in + "" +end diff --git a/tiger/testcases/test17.tig b/tiger/testcases/test17.tig new file mode 100644 index 0000000..5ba01b8 --- /dev/null +++ b/tiger/testcases/test17.tig @@ -0,0 +1,10 @@ +/* error: definition of recursive types is interrupted */ +let +/* define a tree */ +type tree ={key: int, children: treelist} +var d:int :=0 +type treelist = {hd: tree, tl: treelist} + +in + d +end diff --git a/tiger/testcases/test18.tig b/tiger/testcases/test18.tig new file mode 100644 index 0000000..9792e48 --- /dev/null +++ b/tiger/testcases/test18.tig @@ -0,0 +1,15 @@ +/* error : definition of recursive functions is interrupted */ +let + +function do_nothing1(a: int, b: string):int= + (do_nothing2(a+1);0) + +var d:=0 + +function do_nothing2(d: int):string = + (do_nothing1(d, "str");" ") + +in + do_nothing1(0, "str2") +end + diff --git a/tiger/testcases/test19.tig b/tiger/testcases/test19.tig new file mode 100644 index 0000000..2912ca4 --- /dev/null +++ b/tiger/testcases/test19.tig @@ -0,0 +1,13 @@ +/* error : second function uses variables local to the first one, undeclared variable */ +let + +function do_nothing1(a: int, b: string):int= + (do_nothing2(a+1);0) + +function do_nothing2(d: int):string = + (do_nothing1(a, "str");" ") + +in + do_nothing1(0, "str2") +end + diff --git a/tiger/testcases/test2.tig b/tiger/testcases/test2.tig new file mode 100644 index 0000000..8ee0b96 --- /dev/null +++ b/tiger/testcases/test2.tig @@ -0,0 +1,9 @@ +/* arr1 is valid since expression 0 is int = myint */ +let + type myint = int + type arrtype = array of myint + + var arr1:arrtype := arrtype [10] of 0 +in + arr1 +end diff --git a/tiger/testcases/test20.tig b/tiger/testcases/test20.tig new file mode 100644 index 0000000..e3d21ae --- /dev/null +++ b/tiger/testcases/test20.tig @@ -0,0 +1,3 @@ +/* error: undeclared variable i */ + +while 10 > 5 do (i+1;()) diff --git a/tiger/testcases/test21.tig b/tiger/testcases/test21.tig new file mode 100644 index 0000000..4501854 --- /dev/null +++ b/tiger/testcases/test21.tig @@ -0,0 +1,13 @@ +/* error : procedure returns value and procedure is used in arexpr */ +let + +/* calculate n! */ +function nfactor(n: int) = + if n = 0 + then 1 + else n * nfactor(n-1) + +in + nfactor(10) +end + diff --git a/tiger/testcases/test22.tig b/tiger/testcases/test22.tig new file mode 100644 index 0000000..b6f2ef3 --- /dev/null +++ b/tiger/testcases/test22.tig @@ -0,0 +1,8 @@ +/* error : field not in record type */ + +let + type rectype = {name:string , id:int} + var rec1 := rectype {name="Name", id=0} +in + rec1.nam := "asd" +end diff --git a/tiger/testcases/test23.tig b/tiger/testcases/test23.tig new file mode 100644 index 0000000..e501c2a --- /dev/null +++ b/tiger/testcases/test23.tig @@ -0,0 +1,9 @@ +/* error : type mismatch */ + +let + type rectype = {name:string , id:int} + var rec1 := rectype {name="aname", id=0} +in + rec1.name := 3; + rec1.id := "" +end diff --git a/tiger/testcases/test24.tig b/tiger/testcases/test24.tig new file mode 100644 index 0000000..2f51aef --- /dev/null +++ b/tiger/testcases/test24.tig @@ -0,0 +1,7 @@ +/* error : variable not array */ +let + var d:=0 +in + d[3] +end + diff --git a/tiger/testcases/test25.tig b/tiger/testcases/test25.tig new file mode 100644 index 0000000..8e9db43 --- /dev/null +++ b/tiger/testcases/test25.tig @@ -0,0 +1,7 @@ +/* error : variable not record */ +let + var d:=0 +in + d.f +end + diff --git a/tiger/testcases/test26.tig b/tiger/testcases/test26.tig new file mode 100644 index 0000000..bdd89fe --- /dev/null +++ b/tiger/testcases/test26.tig @@ -0,0 +1,3 @@ +/* error : integer required */ + +3 + "var" diff --git a/tiger/testcases/test27.tig b/tiger/testcases/test27.tig new file mode 100644 index 0000000..957adfe --- /dev/null +++ b/tiger/testcases/test27.tig @@ -0,0 +1,8 @@ +/* locals hide globals */ +let + var a:=0 + + function g(a:int):int = a +in + g(2) +end diff --git a/tiger/testcases/test28.tig b/tiger/testcases/test28.tig new file mode 100644 index 0000000..61db8cb --- /dev/null +++ b/tiger/testcases/test28.tig @@ -0,0 +1,10 @@ +/* error : different record types */ + +let + type rectype1 = {name:string , id:int} + type rectype2 = {name:string , id:int} + + var rec1: rectype1 := rectype2 {name="Name", id=0} +in + rec1 +end diff --git a/tiger/testcases/test29.tig b/tiger/testcases/test29.tig new file mode 100644 index 0000000..9692eb4 --- /dev/null +++ b/tiger/testcases/test29.tig @@ -0,0 +1,10 @@ +/* error : different array types */ + +let + type arrtype1 = array of int + type arrtype2 = array of int + + var arr1: arrtype1 := arrtype2 [10] of 0 +in + arr1 +end diff --git a/tiger/testcases/test3.tig b/tiger/testcases/test3.tig new file mode 100644 index 0000000..7f03ff0 --- /dev/null +++ b/tiger/testcases/test3.tig @@ -0,0 +1,8 @@ +/* a record type and a record variable */ +let + type rectype = {name:string, age:int} + var rec1:rectype := rectype {name="Nobody", age=1000} +in + rec1.name := "Somebody"; + rec1 +end diff --git a/tiger/testcases/test30.tig b/tiger/testcases/test30.tig new file mode 100644 index 0000000..fa5c96b --- /dev/null +++ b/tiger/testcases/test30.tig @@ -0,0 +1,10 @@ +/* synonyms are fine */ + +let + type a = array of int + type b = a + + var arr1:a := b [10] of 0 +in + arr1[2] +end diff --git a/tiger/testcases/test31.tig b/tiger/testcases/test31.tig new file mode 100644 index 0000000..47d9449 --- /dev/null +++ b/tiger/testcases/test31.tig @@ -0,0 +1,6 @@ +/* error : type constraint and init value differ */ +let + var a:int := " " +in + a +end diff --git a/tiger/testcases/test32.tig b/tiger/testcases/test32.tig new file mode 100644 index 0000000..95ffedd --- /dev/null +++ b/tiger/testcases/test32.tig @@ -0,0 +1,9 @@ +/* error : initializing exp and array type differ */ + +let + type arrayty = array of int + + var a := arrayty [10] of " " +in + 0 +end diff --git a/tiger/testcases/test33.tig b/tiger/testcases/test33.tig new file mode 100644 index 0000000..099ab39 --- /dev/null +++ b/tiger/testcases/test33.tig @@ -0,0 +1,6 @@ +/* error : unknown type */ +let + var a:= rectype {} +in + 0 +end diff --git a/tiger/testcases/test34.tig b/tiger/testcases/test34.tig new file mode 100644 index 0000000..3929a3c --- /dev/null +++ b/tiger/testcases/test34.tig @@ -0,0 +1,6 @@ +/* error : formals and actuals have different types */ +let + function g (a:int , b:string):int = a +in + g("one", "two") +end diff --git a/tiger/testcases/test35.tig b/tiger/testcases/test35.tig new file mode 100644 index 0000000..8c6d01d --- /dev/null +++ b/tiger/testcases/test35.tig @@ -0,0 +1,6 @@ +/* error : formals are more then actuals */ +let + function g (a:int , b:string):int = a +in + g("one") +end diff --git a/tiger/testcases/test36.tig b/tiger/testcases/test36.tig new file mode 100644 index 0000000..30cd55a --- /dev/null +++ b/tiger/testcases/test36.tig @@ -0,0 +1,6 @@ +/* error : formals are fewer then actuals */ +let + function g (a:int , b:string):int = a +in + g(3,"one",5) +end diff --git a/tiger/testcases/test37.tig b/tiger/testcases/test37.tig new file mode 100644 index 0000000..e13c284 --- /dev/null +++ b/tiger/testcases/test37.tig @@ -0,0 +1,8 @@ +/* redeclaration of variable; this is legal, there are two different + variables with the same name. The second one hides the first. */ +let + var a := 0 + var a := " " +in + 0 +end diff --git a/tiger/testcases/test38.tig b/tiger/testcases/test38.tig new file mode 100644 index 0000000..66843c9 --- /dev/null +++ b/tiger/testcases/test38.tig @@ -0,0 +1,9 @@ +/* This is illegal, since there are two types with the same name + in the same (consecutive) batch of mutually recursive types. + See also test47 */ +let + type a = int + type a = string +in + 0 +end diff --git a/tiger/testcases/test39.tig b/tiger/testcases/test39.tig new file mode 100644 index 0000000..3cccaa9 --- /dev/null +++ b/tiger/testcases/test39.tig @@ -0,0 +1,9 @@ +/* This is illegal, since there are two functions with the same name + in the same (consecutive) batch of mutually recursive functions. + See also test48 */ +let + function g(a:int):int = a + function g(a:int):int = a +in + 0 +end diff --git a/tiger/testcases/test4.tig b/tiger/testcases/test4.tig new file mode 100644 index 0000000..59fd5b8 --- /dev/null +++ b/tiger/testcases/test4.tig @@ -0,0 +1,13 @@ +/* define a recursive function */ +let + +/* calculate n! */ +function nfactor(n: int): int = + if n = 0 + then 1 + else n * nfactor(n-1) + +in + nfactor(10) +end + diff --git a/tiger/testcases/test40.tig b/tiger/testcases/test40.tig new file mode 100644 index 0000000..f54bc02 --- /dev/null +++ b/tiger/testcases/test40.tig @@ -0,0 +1,7 @@ +/* error : procedure returns value */ +let + function g(a:int) = a +in + g(2) +end + diff --git a/tiger/testcases/test41.tig b/tiger/testcases/test41.tig new file mode 100644 index 0000000..49ea5c3 --- /dev/null +++ b/tiger/testcases/test41.tig @@ -0,0 +1,10 @@ +/* local types hide global */ +let + type a = int +in + let + type a = string + in + 0 + end +end diff --git a/tiger/testcases/test42.tig b/tiger/testcases/test42.tig new file mode 100644 index 0000000..32ad3e4 --- /dev/null +++ b/tiger/testcases/test42.tig @@ -0,0 +1,30 @@ +/* correct declarations */ +let + +type arrtype1 = array of int +type rectype1 = {name:string, address:string, id: int , age: int} +type arrtype2 = array of rectype1 +type rectype2 = {name : string, dates: arrtype1} + +type arrtype3 = array of string + +var arr1 := arrtype1 [10] of 0 +var arr2 := arrtype2 [5] of rectype1 {name="aname", address="somewhere", id=0, age=0} +var arr3:arrtype3 := arrtype3 [100] of "" + +var rec1 := rectype1 {name="Kapoios", address="Kapou", id=02432, age=44} +var rec2 := rectype2 {name="Allos", dates= arrtype1 [3] of 1900} + +in + +arr1[0] := 1; +arr1[9] := 3; +arr2[3].name := "kati"; +arr2[1].age := 23; +arr3[34] := "sfd"; + +rec1.name := "sdf"; +rec2.dates[0] := 2323; +rec2.dates[2] := 2323 + +end diff --git a/tiger/testcases/test43.tig b/tiger/testcases/test43.tig new file mode 100644 index 0000000..c1d96af --- /dev/null +++ b/tiger/testcases/test43.tig @@ -0,0 +1,7 @@ +/* initialize with unit and causing type mismatch in addition */ + +let + var a := () +in + a + 3 +end diff --git a/tiger/testcases/test44.tig b/tiger/testcases/test44.tig new file mode 100644 index 0000000..afae869 --- /dev/null +++ b/tiger/testcases/test44.tig @@ -0,0 +1,11 @@ +/* valid nil initialization and assignment */ +let + + type rectype = {name:string, id:int} + var b:rectype := nil + +in + + b := nil + +end diff --git a/tiger/testcases/test45.tig b/tiger/testcases/test45.tig new file mode 100644 index 0000000..21f9555 --- /dev/null +++ b/tiger/testcases/test45.tig @@ -0,0 +1,8 @@ +/* error: initializing nil expressions not constrained by record type */ +let + type rectype = {name:string, id:int} + + var a:= nil +in + a +end diff --git a/tiger/testcases/test46.tig b/tiger/testcases/test46.tig new file mode 100644 index 0000000..4aed888 --- /dev/null +++ b/tiger/testcases/test46.tig @@ -0,0 +1,8 @@ +/* valid rec comparisons */ +let + type rectype = {name:string, id:int} + var b:rectype := nil +in + b = nil; + b <> nil +end diff --git a/tiger/testcases/test47.tig b/tiger/testcases/test47.tig new file mode 100644 index 0000000..163eba3 --- /dev/null +++ b/tiger/testcases/test47.tig @@ -0,0 +1,11 @@ +/* This is legal. The second type "a" simply hides the first one. + Because of the intervening variable declaration, the two "a" types + are not in the same batch of mutually recursive types. + See also test38 */ +let + type a = int + var b := 4 + type a = string +in + 0 +end diff --git a/tiger/testcases/test48.tig b/tiger/testcases/test48.tig new file mode 100644 index 0000000..7ba4e14 --- /dev/null +++ b/tiger/testcases/test48.tig @@ -0,0 +1,11 @@ +/* This is legal. The second function "g" simply hides the first one. + Because of the intervening variable declaration, the two "g" functions + are not in the same batch of mutually recursive functions. + See also test39 */ +let + function g(a:int):int = a + type t = int + function g(a:int):int = a +in + 0 +end diff --git a/tiger/testcases/test49.tig b/tiger/testcases/test49.tig new file mode 100644 index 0000000..3aa9e3f --- /dev/null +++ b/tiger/testcases/test49.tig @@ -0,0 +1,8 @@ +/* error: syntax error, nil should not be preceded by type-id. */ +let + type rectype = {name:string, id:int} + + var a:= rectype nil +in + a +end diff --git a/tiger/testcases/test5.tig b/tiger/testcases/test5.tig new file mode 100644 index 0000000..5af7ca5 --- /dev/null +++ b/tiger/testcases/test5.tig @@ -0,0 +1,14 @@ +/* define valid recursive types */ +let +/* define a list */ +type intlist = {hd: int, tl: intlist} + +/* define a tree */ +type tree ={key: int, children: treelist} +type treelist = {hd: tree, tl: treelist} + +var lis:intlist := intlist { hd=0, tl= nil } + +in + lis +end diff --git a/tiger/testcases/test6.tig b/tiger/testcases/test6.tig new file mode 100644 index 0000000..c0daa0d --- /dev/null +++ b/tiger/testcases/test6.tig @@ -0,0 +1,13 @@ +/* define valid mutually recursive procedures */ +let + +function do_nothing1(a: int, b: string)= + do_nothing2(a+1) + +function do_nothing2(d: int) = + do_nothing1(d, "str") + +in + do_nothing1(0, "str2") +end + diff --git a/tiger/testcases/test7.tig b/tiger/testcases/test7.tig new file mode 100644 index 0000000..534c2a2 --- /dev/null +++ b/tiger/testcases/test7.tig @@ -0,0 +1,13 @@ +/* define valid mutually recursive functions */ +let + +function do_nothing1(a: int, b: string):int= + (do_nothing2(a+1);0) + +function do_nothing2(d: int):string = + (do_nothing1(d, "str");" ") + +in + do_nothing1(0, "str2") +end + diff --git a/tiger/testcases/test8.tig b/tiger/testcases/test8.tig new file mode 100644 index 0000000..d46f3ec --- /dev/null +++ b/tiger/testcases/test8.tig @@ -0,0 +1,2 @@ +/* correct if */ +if (10 > 20) then 30 else 40 diff --git a/tiger/testcases/test9.tig b/tiger/testcases/test9.tig new file mode 100644 index 0000000..64ff9f9 --- /dev/null +++ b/tiger/testcases/test9.tig @@ -0,0 +1,3 @@ +/* error : types of then - else differ */ + +if (5>4) then 13 else " "