Add the tiger source code bundle from the book site

Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
Mariano Uvalle 2024-12-18 15:18:45 -08:00
parent 915660c8a7
commit 33d8bac511
87 changed files with 3252 additions and 0 deletions

20
tiger/chap1/slp.sml Normal file
View file

@ -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"]))

80
tiger/chap10/graph.sml Normal file
View file

@ -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

109
tiger/chap12/runtime.c Normal file
View file

@ -0,0 +1,109 @@
#undef __STDC__
#include <stdio.h>
int *initArray(int size, int init)
{int i;
int *a = (int *)malloc(size*sizeof(int));
for(i=0;i<size;i++) a[i]=init;
return a;
}
int *allocRecord(int size)
{int i;
int *p, *a;
p = a = (int *)malloc(size);
for(i=0;i<size;i+=sizeof(int)) *p++ = 0;
return a;
}
struct string {int length; unsigned char chars[1];};
int stringEqual(struct string *s, struct string *t)
{int i;
if (s==t) return 1;
if (s->length!=t->length) return 0;
for(i=0;i<s->length;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;i<s->length;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;i<n;i++) t->chars[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;i<a->length;i++)
t->chars[i]=a->chars[i];
for(i=0;i<b->length;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 &empty;
else return consts+i;
}

17
tiger/chap2/driver.sml Normal file
View file

@ -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

53
tiger/chap2/errormsg.sml Normal file
View file

@ -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<pos then app print [":",
Int.toString n,
".",
Int.toString (pos-a)]
else look(rest,n-1)
| look _ = print "0.0"
in anyErrors := true;
print (!fileName);
look(!linePos,!lineNum);
print ":";
print msg;
print "\n"
end
fun impossible msg =
(app print ["Error: Compiler bug: ",msg,"\n"];
TextIO.flushOut TextIO.stdOut;
raise Error)
end (* structure ErrorMsg *)

8
tiger/chap2/sources.cm Normal file
View file

@ -0,0 +1,8 @@
Group is
driver.sml
errormsg.sml
tokens.sig
tokens.sml
tiger.lex
smlnj-lib.cm

18
tiger/chap2/tiger.lex Normal file
View file

@ -0,0 +1,18 @@
type pos = int
type lexresult = Tokens.token
val lineNum = ErrorMsg.lineNum
val linePos = ErrorMsg.linePos
fun err(p1,p2) = ErrorMsg.error p1
fun eof() = let val pos = hd(!linePos) in Tokens.EOF(pos,pos) end
%%
%%
\n => (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());

49
tiger/chap2/tokens.sig Normal file
View file

@ -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

51
tiger/chap2/tokens.sml Normal file
View file

@ -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

53
tiger/chap3/errormsg.sml Normal file
View file

@ -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<pos then app print [":",
Int.toString n,
".",
Int.toString (pos-a)]
else look(rest,n-1)
| look _ = print "0.0"
in anyErrors := true;
print (!fileName);
look(!linePos,!lineNum);
print ":";
print msg;
print "\n"
end
fun impossible msg =
(app print ["Error: Compiler bug: ",msg,"\n"];
TextIO.flushOut TextIO.stdOut;
raise Error)
end (* structure ErrorMsg *)

22
tiger/chap3/parsetest.sml Normal file
View file

@ -0,0 +1,22 @@
structure Parse : sig val parse : string -> 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

9
tiger/chap3/sources.cm Normal file
View file

@ -0,0 +1,9 @@
Group is
tiger.lex
errormsg.sml
parsetest.sml
tiger.grm
smlnj-lib.cm
ml-yacc-lib.cm

38
tiger/chap3/tiger.grm Normal file
View file

@ -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: ()

988
tiger/chap3/tiger.lex.sml Normal file
View file

@ -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

52
tiger/chap4/absyn.sml Normal file
View file

@ -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

53
tiger/chap4/errormsg.sml Normal file
View file

@ -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<pos then app print [":",
Int.toString n,
".",
Int.toString (pos-a)]
else look(rest,n-1)
| look _ = print "0.0"
in anyErrors := true;
print (!fileName);
look(!linePos,!lineNum);
print ":";
print msg;
print "\n"
end
fun impossible msg =
(app print ["Error: Compiler bug: ",msg,"\n"];
TextIO.flushOut TextIO.stdOut;
raise Error)
end (* structure ErrorMsg *)

22
tiger/chap4/parse.sml Normal file
View file

@ -0,0 +1,22 @@
structure Parse : sig val parse : string -> 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

128
tiger/chap4/prabsyn.sml Normal file
View file

@ -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

13
tiger/chap4/sources.cm Normal file
View file

@ -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

43
tiger/chap4/symbol.sml Normal file
View file

@ -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

9
tiger/chap4/table.sig Normal file
View file

@ -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

9
tiger/chap4/table.sml Normal file
View file

@ -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

40
tiger/chap4/tiger.grm Normal file
View file

@ -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)

16
tiger/chap5/types.sml Normal file
View file

@ -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

64
tiger/chap7/printtree.sml Normal file
View file

@ -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

11
tiger/chap7/temp.sig Normal file
View file

@ -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

24
tiger/chap7/temp.sml Normal file
View file

@ -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

58
tiger/chap7/tree.sml Normal file
View file

@ -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

183
tiger/chap8/canon.sml Normal file
View file

@ -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

39
tiger/chap9/assem.sml Normal file
View file

@ -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

183
tiger/chap9/canon.sml Normal file
View file

@ -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

23
tiger/chap9/flowgraph.sml Normal file
View file

@ -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

23
tiger/chap9/graph.sig Normal file
View file

@ -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

80
tiger/chap9/graph.sml Normal file
View file

@ -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

39
tiger/chap9/main.sml Normal file
View file

@ -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

109
tiger/chap9/runtime.c Normal file
View file

@ -0,0 +1,109 @@
#undef __STDC__
#include <stdio.h>
int *initArray(int size, int init)
{int i;
int *a = (int *)malloc(size*sizeof(int));
for(i=0;i<size;i++) a[i]=init;
return a;
}
int *allocRecord(int size)
{int i;
int *p, *a;
p = a = (int *)malloc(size);
for(i=0;i<size;i+=sizeof(int)) *p++ = 0;
return a;
}
struct string {int length; unsigned char chars[1];};
int stringEqual(struct string *s, struct string *t)
{int i;
if (s==t) return 1;
if (s->length!=t->length) return 0;
for(i=0;i<s->length;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;i<s->length;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;i<n;i++) t->chars[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;i<a->length;i++)
t->chars[i]=a->chars[i];
for(i=0;i<b->length;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 &empty;
else return consts+i;
}

56
tiger/testcases/merge.tig Normal file
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
/* error : body of while not unit */
while(10 > 5) do 5+6

View file

@ -0,0 +1,3 @@
/* error hi expr is not int, and index variable erroneously assigned to. */
for i:=10 to " " do
i := i - 1

View file

@ -0,0 +1,7 @@
/* valid for and let */
let
var a:= 0
in
for i:=0 to 100 do (a:=a+1;())
end

View file

@ -0,0 +1,3 @@
/* error: comparison of incompatible types */
3 > "df"

View file

@ -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

View file

@ -0,0 +1,3 @@
/* error : if-then returns non unit */
if 20 then 3

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,3 @@
/* error: undeclared variable i */
while 10 > 5 do (i+1;())

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,7 @@
/* error : variable not array */
let
var d:=0
in
d[3]
end

View file

@ -0,0 +1,7 @@
/* error : variable not record */
let
var d:=0
in
d.f
end

View file

@ -0,0 +1,3 @@
/* error : integer required */
3 + "var"

View file

@ -0,0 +1,8 @@
/* locals hide globals */
let
var a:=0
function g(a:int):int = a
in
g(2)
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,6 @@
/* error : type constraint and init value differ */
let
var a:int := " "
in
a
end

View file

@ -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

View file

@ -0,0 +1,6 @@
/* error : unknown type */
let
var a:= rectype {}
in
0
end

View file

@ -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

View file

@ -0,0 +1,6 @@
/* error : formals are more then actuals */
let
function g (a:int , b:string):int = a
in
g("one")
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

13
tiger/testcases/test4.tig Normal file
View file

@ -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

View file

@ -0,0 +1,7 @@
/* error : procedure returns value */
let
function g(a:int) = a
in
g(2)
end

View file

@ -0,0 +1,10 @@
/* local types hide global */
let
type a = int
in
let
type a = string
in
0
end
end

View file

@ -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

View file

@ -0,0 +1,7 @@
/* initialize with unit and causing type mismatch in addition */
let
var a := ()
in
a + 3
end

View file

@ -0,0 +1,11 @@
/* valid nil initialization and assignment */
let
type rectype = {name:string, id:int}
var b:rectype := nil
in
b := nil
end

View file

@ -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

View file

@ -0,0 +1,8 @@
/* valid rec comparisons */
let
type rectype = {name:string, id:int}
var b:rectype := nil
in
b = nil;
b <> nil
end

View file

@ -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

View file

@ -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

View file

@ -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

14
tiger/testcases/test5.tig Normal file
View file

@ -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

13
tiger/testcases/test6.tig Normal file
View file

@ -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

13
tiger/testcases/test7.tig Normal file
View file

@ -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

View file

@ -0,0 +1,2 @@
/* correct if */
if (10 > 20) then 30 else 40

View file

@ -0,0 +1,3 @@
/* error : types of then - else differ */
if (5>4) then 13 else " "