Top > TigerBook > PROGRAM5
Counter: 3800, today: 1, yesterday: 0

Chapter 5 の PROGRAM

PROGRAM

tiger.grm 修正後

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

%nonterm  exp of A.exp
        | program of A.exp
	| lvalue of A.var
	| novalue of A.exp
	| sequensing of A.exp
	| expsemilist of (A.exp * A.pos) list
	| functionCall of A.exp
	| explistopt of A.exp list
	| explist of A.exp list
	| opExpr of A.exp
	| recordCreate of A.exp
	| typeid of A.symbol
	| idExpList of (A.symbol * A.exp * A.pos) list
	| recField of (A.symbol * A.exp * A.pos)
	| arrayCreate of A.exp
	| assignment of A.exp
	| ifThenElse of A.exp
	| ifThen of A.exp
	| whileClause  of A.exp
	| forClause of A.exp
	| letexp of A.exp
	| expseq of (A.exp * A.pos) list
	| parentheses of A.exp
	| decs of A.dec list
	| dec of A.dec
	| tydeclist of {name:A.symbol, pos:pos, ty:A.ty} list
	| tydec of {name:A.symbol, pos:pos, ty:A.ty}
	| ty of A.ty
	| tyfields of A.field list
	| tyfieldlist of A.field list
	| tyfield of A.field
	| vardec of A.dec
	| fundec of A.fundec
	| fundeclist of A.fundec list

(*	| valuelessExp | stringCmp | precedenceOp | associativityOp
	| arrRecAssign | extent *)
%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 ("")


(*%nonassoc ASSIGN DO OF THEN ELSE*)
%nonassoc ASSIGN
%left DO THEN OF
%left ELSE
%left OR
%left AND
%nonassoc EQ NEQ LT LE GT GE
%left PLUS MINUS
%left TIMES DIVIDE
%left UNARYMINUS

%%

program	: exp        (exp)

(***** Expressions *****)
exp: lvalue          (A.VarExp lvalue)
   | ID              (A.VarExp (A.SimpleVar (Symbol.symbol ID, IDleft)))
   | novalue         (novalue)
   | NIL             (A.NilExp)
   | sequensing      (sequensing)
   | INT             (A.IntExp INT)
   | STRING          (A.StringExp (STRING, STRINGleft))
   | functionCall    (functionCall)
   | opExpr          (opExpr)
   | recordCreate    (recordCreate)
   | arrayCreate     (arrayCreate)
   | assignment      (assignment)
   | ifThenElse      (ifThenElse)
   | ifThen          (ifThen)
   | whileClause     (whileClause)
   | forClause       (forClause)
   | BREAK           (A.BreakExp BREAKleft)
   | letexp          (letexp)
   | parentheses     (parentheses)

lvalue :  ID DOT ID          (A.FieldVar  (A.SimpleVar(Symbol.symbol ID1, ID1left), Symbol.symbol ID2, ID2left))
       | ID LBRACK exp RBRACK (A.SubscriptVar (A.SimpleVar(Symbol.symbol ID, IDleft), exp, IDleft))
       | lvalue DOT ID            (A.FieldVar  (lvalue, Symbol.symbol ID, IDleft)) (*fix*)
       | lvalue LBRACK exp RBRACK (A.SubscriptVar (lvalue, exp, lvalueleft))

novalue : LPAREN RPAREN (A.SeqExp [])


sequensing     : LPAREN expsemilist RPAREN (A.SeqExp expsemilist)

expsemilist : expsemilist SEMICOLON exp (expsemilist @ [(exp, expleft)])
    	    | exp SEMICOLON exp   ((exp1,exp1left) :: [(exp2, exp2left)])  (* Excl. Parentheses *)

functionCall : ID LPAREN explistopt RPAREN (A.CallExp {func=Symbol.symbol ID, args=explistopt, pos=IDleft})
explistopt : explist (explist)
	   |         ([])  (* empty *)
explist    : explist COMMA exp (explist @ [exp])
           | exp               ([exp])

opExpr  : exp DIVIDE exp (A.OpExp {left=exp1,oper=A.DivideOp,right=exp2,pos=DIVIDEleft})
	| exp TIMES exp  (A.OpExp {left=exp1,oper=A.TimesOp ,right=exp2,pos=TIMESleft})
	| exp MINUS exp  (A.OpExp {left=exp1,oper=A.MinusOp ,right=exp2,pos=MINUSleft})
	| exp PLUS  exp  (A.OpExp {left=exp1,oper=A.PlusOp  ,right=exp2,pos=PLUSleft})
	| exp EQ  exp (A.OpExp {left=exp1, oper=A.EqOp,  right=exp2, pos=EQleft})
	| exp NEQ exp (A.OpExp {left=exp1, oper=A.NeqOp, right=exp2, pos=NEQleft})
	| exp GE  exp (A.OpExp {left=exp1, oper=A.GeOp,  right=exp2, pos=GEleft})
	| exp GT  exp (A.OpExp {left=exp1, oper=A.GtOp,  right=exp2, pos=GTleft})
	| exp LE  exp (A.OpExp {left=exp1, oper=A.LeOp,  right=exp2, pos=LEleft})
	| exp LT  exp (A.OpExp {left=exp1, oper=A.LtOp,  right=exp2, pos=LTleft})
	| exp AND exp (A.IfExp {test=exp1, then'=exp2, else'=SOME (A.IntExp 0), pos=ANDleft})
	| exp OR  exp (A.IfExp {test=exp1, then'=A.IntExp 1, else'=SOME exp2, pos=ORleft})
        | MINUS exp %prec UNARYMINUS (A.OpExp {left=A.IntExp 0, oper=A.MinusOp,  right=exp1, pos=MINUSleft})

(*recordCreate   : typeid LBRACE idExpList RBRACE () (* typeid *)*)
recordCreate   : ID LBRACE idExpList RBRACE
                 (A.RecordExp {fields=idExpList, typ=Symbol.symbol ID, pos=IDleft}) (* typeid *)
		 | ID LBRACE RBRACE (A.RecordExp {fields=[], typ=Symbol.symbol ID, pos=IDleft}) (* empty record*)
typeid : ID (Symbol.symbol ID)
idExpList : recField ([recField])
	  | idExpList COMMA recField ( idExpList @ [recField]) (* Correct! *)
recField : ID EQ exp ((Symbol.symbol ID, exp, IDleft))

(*arrayCreate    : typeid LBRACK exp RBRACK OF exp () (* typeid *)*)
arrayCreate    : ID LBRACK exp RBRACK OF exp
		(A.ArrayExp {typ=Symbol.symbol ID, size=exp1, init=exp2, pos=IDleft})
		(* typeid *)
assignment     : lvalue ASSIGN exp
		(A.AssignExp {var=lvalue, exp=exp, pos=ASSIGNleft})
                | ID ASSIGN exp
                (A.AssignExp {var=(A.SimpleVar(Symbol.symbol ID, IDleft)), exp=exp, pos=ASSIGNleft})
ifThen         : IF exp THEN exp
		(A.IfExp {test=exp1, then'=exp2, pos=IFleft, else'=NONE})
ifThenElse     : IF exp THEN exp ELSE exp
		(A.IfExp {test=exp1, then'=exp2, else'=SOME exp3, pos=IFleft})
whileClause    : WHILE exp DO exp
		(A.WhileExp {test=exp1, body=exp2, pos=WHILEleft})
forClause      : FOR ID ASSIGN exp TO exp DO exp
		(A.ForExp {var=Symbol.symbol ID, lo=exp1,hi=exp2, body=exp3, escape=ref true, pos=FORleft})
letexp         : LET decs IN expseq END
		(A.LetExp {decs=decs, body=A.SeqExp expseq, pos=LETleft})
expseq : expsemilist (expsemilist)
       | exp         ([(exp,expleft)])
       |             ([(A.SeqExp [],defaultPos)])  (* novalue *)
parentheses    : LPAREN exp RPAREN        (exp)

(***** Declaration *****)
decs :               ([]) (* empty *)
     |  decs dec     (decs @ [dec])

dec : tydeclist  (A.TypeDec tydeclist)
    | vardec (vardec)
    | fundeclist (A.FunctionDec fundeclist)

tydeclist : tydec tydeclist (tydeclist @ [tydec])
      | tydec ([tydec])
tydec : TYPE typeid EQ ty ({name=typeid, ty=ty, pos=TYPEleft})

ty : typeid                 (A.NameTy (typeid, typeidleft))
   | LBRACE tyfields RBRACE (A.RecordTy tyfields)
   | ARRAY OF typeid        (A.ArrayTy (typeid, typeidleft))

tyfields : ([])  (* empty *)
	 | tyfieldlist                  (tyfieldlist)
tyfieldlist : tyfieldlist COMMA tyfield (tyfieldlist @ [tyfield])
	    | tyfield                   ([tyfield])

tyfield : ID COLON typeid
		({name=Symbol.symbol ID, typ=typeid, escape=ref true, pos=IDleft})

vardec : VAR ID ASSIGN exp
		(A.VarDec {name=Symbol.symbol ID, typ=NONE, init=exp, escape=ref true, pos=VARleft})
       | VAR ID COLON typeid ASSIGN exp
		(A.VarDec {name=Symbol.symbol ID, typ=SOME (typeid,typeidleft), init=exp, escape=ref true, pos=VARleft})

fundeclist : fundec            ([fundec])
	   | fundeclist fundec (fundeclist @ [fundec])

fundec : FUNCTION ID LPAREN tyfields RPAREN EQ exp
		({name=Symbol.symbol ID, params=tyfields, result=NONE, body=exp, pos=FUNCTIONleft})
       | FUNCTION ID LPAREN tyfields RPAREN COLON typeid EQ exp
		({name=Symbol.symbol ID, params=tyfields, result=SOME (typeid,typeidleft), body=exp, pos=FUNCTIONleft})

env.sml

VarEntry の access フィールドはこの章では使ってないので削除してある。 今後必要になったときに追加か。

signature ENV =
sig
    type access
    type ty
    datatype enventry = VarEntry of {ty:ty}
                      | FunEntry of {formals: ty list, result:ty}
    val base_tenv : ty Symbol.table
    val base_venv : enventry Symbol.table
end
structure Env : ENV = struct

type access = unit  (* dummy *)
type ty = Types.ty
datatype enventry = VarEntry of {ty:ty}
                  | FunEntry of {formals: ty list, result:ty}
val base_tenv : ty Symbol.table =
    let
        val te1 = Symbol.empty
        val te2 = Symbol.enter(te1,(Symbol.symbol "int"),Types.INT)
        val te3 = Symbol.enter(te2,(Symbol.symbol "string"),Types.STRING)
    in te3 end
val base_venv : enventry Symbol.table = Symbol.empty
end

semant.sml

変なコメントが残っていたり、エラー処理が未実装だったりするが testcase 1〜48 は通ったよう。 (queens, merge はライブラリが無いのでエラーになる)

structure Semant : sig val transProg : Absyn.exp -> unit end =
struct

structure A = Absyn

type venv = Env.enventry Symbol.table
type tenv = Types.ty Symbol.table
type expty = {exp: Translate.exp, ty: Types.ty}

exception Unimplemented

val error = ErrorMsg.error

fun transTy (te, t) = raise Unimplemented
fun actual_ty ty =
    case ty of
	Types.NAME (t,r) =>
	(case !r of NONE => (error 0 ("Cannot resolve type "^Symbol.name t);Types.UNIT)
	 	  | SOME t1 => actual_ty t1)
      | _ => ty

fun checkInt ({exp=e,ty=t},p) =
    case t of Types.INT => () | _ => error p "Integer required"
fun checkUnit ({exp=e,ty=t},p) =
    case t of Types.UNIT => () | _ => error p "Unit required"
fun checkArray ({exp=e,ty=t},p) =
    case t of Types.ARRAY _ => () | _ => error p "Array required"

fun checkSame (t1,t2,p) =
    case (t1,t2) of
	(Types.RECORD a, Types.RECORD b) => if a=b then () else error p "Type mismatched"
      | (Types.RECORD _, Types.NIL     ) => ()
      | (Types.NIL     , Types.RECORD _) => ()
      | (Types.NIL     , Types.NIL     ) => ()
      | (Types.NIL     , _             ) => error p "Illegal nil"
      | (_             , Types.NIL     ) => error p "Illegal nil"
      | (a             , b             ) => if a=b then () else error p "Type mismatched"

fun checkNotNil (t,p) =
    case t of Types.NIL => error p "Other than nil required" | _ => ()
(*
fun checkString ({exp=e,ty=t},p) =
    case t of Types.STRING => () | _ => error p "String required"
fun checkNil ({exp=e,ty=t},p) =
    case t of Types.NIL => () | _ => error p "Nil required"
fun checkRecord ({exp=e,ty=t},p) =
    case t of Types.RECORD _ => () | _ => error p "Record required"
*)

fun transExp (ve, te, e) = 
    let
	fun analyze_var v =
	    case v of
		A.SimpleVar (sym,p) =>
		(case Symbol.look(ve,sym) of
		     SOME(Env.VarEntry{ty}) => {exp=(), ty=actual_ty ty}
		   | _ => (error p("Undefined variable "^Symbol.name sym);
			   {exp=(),ty=Types.INT} )
		)
	      | A.FieldVar (v,sym,p) =>
		let val {exp=_,ty=recty} = analyze_var v 
		    val sytl =
			case (actual_ty recty) of
			    Types.RECORD (a,u) => a
			  | _ => (error p "Record required";[]) 
		    val findt =
			case List.find (fn (s,t) => sym=s) sytl of
			    SOME (s,t) => actual_ty t
			  | NONE => (error p "Record field not found";Types.UNIT)
		in {exp=(),ty=findt} end
	      | A.SubscriptVar (v,e,p) =>
		let val avar = analyze_var v
		    val {exp=_, ty=avarty} = avar
		    val subty = case actual_ty avarty of
				    Types.ARRAY (ty,_) => actual_ty ty
				  | _ => (error p "Array required"; Types.UNIT)
		in checkArray (avar, p); {exp=(),ty=subty} end
	and analyze_exp e = (* trexp *)
	    case e of
		A.VarExp v => analyze_var v
	      | A.NilExp => {exp=(), ty=Types.NIL}
	      | A.IntExp i => {exp=(), ty=Types.INT}
	      | A.StringExp (s,p) => {exp=(), ty=Types.STRING}
	      | A.CallExp {func=sym , args=el , pos=p} =>
		let
		    val argl = map analyze_exp el
		    val (fdecl,rt) =
			case Symbol.look(ve,sym) of
			    SOME (Env.FunEntry {formals, result}) => (formals,result)
			  | _ => (error p ("Undefined function "^(Symbol.name sym));
				  ([],Types.UNIT))
		in
		    (* 相互参照がうまくいかない? *)
		    if (map #ty argl) = fdecl then ()
		    else error p "Function call type mismatch";
		    {exp=(), ty=actual_ty rt}
		end
	      | A.OpExp {left=e1, oper=oprr, right=e2, pos=p} =>
		let
		    val et1 = analyze_exp e1
		    val et2 = analyze_exp e2
		    fun cic () = (checkInt(et1, p); checkInt(et2, p);
			{exp=(), ty=Types.INT})
		    val {exp=_, ty=t1} = et1
		    val {exp=_, ty=t2} = et2
		    fun cbc () = (checkSame (actual_ty t1, actual_ty t2, p);
				  {exp=(), ty=Types.INT})
		in case oprr of
		       A.PlusOp => cic ()
		     | A.MinusOp => cic ()
		     | A.TimesOp => cic ()
		     | A.DivideOp => cic ()
		     | _ => cbc ()
		end
	      | A.RecordExp {fields=fl, typ=sym , pos=p} =>
		let val typ = case Symbol.look(te,sym) of
				  NONE => (error p "Not found record-type";
					   Types.UNIT)
				| SOME t => t
		in
		    (* field が全部あるか、そもそもその型が存在するか *)
		    {exp=(), ty=typ} (*仮*)
		end
	      | A.SeqExp epl =>
		let fun analyze_eplist r epl = (*いいかげん*)
			case epl of
			    (e,p) :: tl => analyze_eplist (analyze_exp e) tl
			  | [] => r 
		in analyze_eplist {exp=(), ty=Types.UNIT} epl end
	      | A.AssignExp {var=v, exp=e, pos=p} =>
		let val {exp=_, ty=vtype} = analyze_var v
		    val {exp=_, ty=etype} = analyze_exp e
		    val vt = actual_ty vtype
		    val et = actual_ty etype
		in checkSame (vt,et,p); {exp=(),ty=vt} end
	      | A.IfExp {test=e1, then'=e2 , else'=eo, pos=p} =>
		let val _ = checkInt(analyze_exp e1, p)
		    val {exp=et,ty=tt} = analyze_exp e2
		    val {exp=ee,ty=te} =
			case eo of NONE => {exp=(), ty=Types.UNIT}
				 | SOME e3 => analyze_exp e3
		in
		    if tt <> te then error p "Type mismatch" else ();
		    {exp=(), ty=tt}
		end
	      | A.WhileExp {test=e1 , body=e2 , pos=p}
		=> (checkInt(analyze_exp e1, p); checkUnit(analyze_exp e2, p);
		    {exp=(), ty=Types.UNIT})
	      | A.ForExp {var=sym, escape=_, lo=e1, hi=e2, body=e3, pos=p}
		=> (checkInt(analyze_exp e1, p); checkInt(analyze_exp e2, p);
		    (* var は Int に設定して、body は unit 明示させるのかな *)
		    {exp=(), ty=Types.UNIT})
	      | A.BreakExp _ => {exp=(), ty=Types.UNIT}
	      | A.LetExp {decs=dl, body=e, pos=p} =>
		let val {venv=ve2, tenv=te2} = transDecs(ve,te,dl)
		in transExp (ve2,te2,e) end
	      | A.ArrayExp {typ=sym, size=e1, init=e2, pos=p} =>
		let val {exp=e2e,ty=t2t} = analyze_exp e2
		    val t = case Symbol.look(te,sym) of
				SOME t => (
				case (actual_ty t) of
				    Types.ARRAY (st, _) =>
				    (checkSame (actual_ty st, actual_ty t2t, p);t )
				  | _ => (error p "Type system error";t)
				)
			      | NONE => (error p ("Not Found "^(Symbol.name sym));
					 Types.ARRAY (Types.INT, ref ()))
		in checkInt(analyze_exp e1, p); {exp=(), ty=t} end
    in analyze_exp e end
and transDec (ve, te, d) =
    case d of
	A.FunctionDec fdl =>
	let
	    fun checkDuplicate fdl =
		let fun checkdup item l = 
			case List.find (fn {name,params,result,body,pos} => item=name) l of
			    SOME {name,params,result,body,pos} =>
			    error pos ("Function declaration "^Symbol.name name^" duplicated")
			  | NONE => ()
		in case fdl of
		       {name,params,result,body,pos}::tl => (checkdup name tl; checkDuplicate tl)
		     | [] => ()
		end
	    fun analyze_fundec_hdr ve te ({name=sym, params=fl, result=so, body=e, pos=p}) = 
		let
		    val SOME(result_ty) = 
			case so of SOME(rt,pos) => Symbol.look(te, rt)
				 | NONE => SOME(Types.UNIT)
		    fun transparam ({name, typ, pos, escape}) =
			case Symbol.look(te, typ) of SOME t => {name=name, ty=t}
						   | NONE => raise Unimplemented
		    val params' = map transparam fl
		    val venv' =
			Symbol.enter(ve, sym, Env.FunEntry
						  {formals=map #ty params',
						   result=result_ty})
		in {tenv=te, venv=venv'} end
	    fun analyze_funlist_1st ve te fdl =
		case fdl of
		    hd::tl => let val {tenv,venv}=analyze_fundec_hdr ve te hd in
				  analyze_funlist_1st venv tenv tl end
		  | [] => {venv=ve, tenv=te}
	    fun analyze_funlist_2nd ve te fdl =
		let fun analyze_fundec_body ({name, params, result, body=e, pos}) = 
			let
			    fun transparam ({name, typ, pos, escape}) =
				case Symbol.look(te, typ) of SOME t => {name=name, ty=t}
							   | NONE => raise Unimplemented
			    val params' = map transparam params
			    fun enterparam ({name,ty},venv) =
				Symbol.enter(venv, name, Env.VarEntry{ty=ty})
			    val ve' = foldl enterparam ve params'
			    val {exp,ty} = transExp (ve', te, e)
			    val SOME(rtyp) = case result of SOME (t,p) => Symbol.look(te, t)
						    | NONE => SOME(Types.UNIT)
			in
			    if actual_ty ty = actual_ty rtyp then ()
			    else error pos "Function return type error"
			end
		in case fdl of
		       hd::tl => (analyze_fundec_body hd; analyze_funlist_2nd ve te tl)
		     | [] => ()
		end
	    val _ = checkDuplicate fdl
	    val {tenv=te2,venv=ve2} = analyze_funlist_1st ve te fdl
	    val _ = analyze_funlist_2nd ve2 te2 fdl
	in {venv=ve2, tenv=te2} end
      | A.VarDec {name=sym, escape=_, typ=symo, init=e, pos=p}
	=>(case symo of
	       NONE =>
	       let val {exp,ty} = transExp (ve, te, e)
		   val _ = checkNotNil (ty,p)
	       in {tenv=te,venv=Symbol.enter(ve,sym,Env.VarEntry{ty=ty})} end
	     | SOME (s,p2) =>
	       let val {exp,ty} = transExp (ve, te, e)
		   val t = case Symbol.look(te,s) of
			       SOME t => (checkSame ((actual_ty t),(actual_ty ty),p2);t)
			     | NONE =>(error p2 "Type not exist"; Types.INT)
	       in {tenv=te,venv=Symbol.enter(ve,sym,Env.VarEntry{ty=t})} end
	  )
      | A.TypeDec tyl =>
	let
	    fun checkDuplicate tyl =
		let fun checkdup item l = 
			case List.find (fn {name,ty,pos} => item=name) l of
			    SOME {name,ty,pos} =>
			    error pos ("Type declaration "^Symbol.name name^" duplicated")
			  | NONE => ()
		in case tyl of
		       {name,ty,pos}::tl => (checkdup name tl; checkDuplicate tl)
		     | [] => ()
		end
	    fun analyze_typelist_1st te tyl = (* とりあえず型名だけ登録 *)
		let fun analyze_type_1st te {name=n, ty=t, pos=p} =
			Symbol.enter (te, n, Types.NAME(n,ref NONE))
		in case tyl of
		       hd::tl => analyze_typelist_1st (analyze_type_1st te hd) tl
		     | [] => te
		end
	    fun analyze_type_f te2 ty =
		case ty of
		    A.NameTy (sym,p) => Types.NAME(sym, ref(Symbol.look(te2, sym)))
		  | A.RecordTy fl =>
		    let fun analyze_field {name=sym1, escape=_, typ=sym2, pos=p} =
			    let val ty = case Symbol.look(te2, sym2) of
					     SOME t => t
					   | NONE =>(
					     error p ("Undefined type "^Symbol.name sym2);
					     Types.RECORD ([],ref ()) )
			    in (sym1,ty) end
			fun analyze_fieldlist fl ft =
			    case fl of
				hd::tl => analyze_fieldlist tl ((analyze_field hd)::ft)
			      | [] => ft
		    in Types.RECORD ((analyze_fieldlist fl []), ref ()) end
		  | A.ArrayTy (sym,_) =>
		    let val ty = case Symbol.look (te2, sym) of
				     SOME t => t
				   | NONE => raise Unimplemented
		    in Types.ARRAY (ty, ref ()) end  (* actual_ty だとエラーチェックがおかしくなるが*)
	    fun analyze_typelist_2nd te2 tyl =
		let fun analyze_type_2nd {name=n, ty=t, pos=p} =
			let val typ = SOME(analyze_type_f te2 t)
			in case Symbol.look(te2, n) of
			       SOME (Types.NAME (nt,r)) =>
			       if n=nt then r := typ else error p "System error"
			     | NONE => error p "System error"
			     | SOME _ => ()
			end
		in case tyl of
		       hd::tl => (analyze_type_2nd hd; analyze_typelist_2nd te2 tl)
		     | [] => ()
		end
	    fun checkLoop te tyl = 
		let fun checkLoopItem name ty p visl =
			case ty of
			    Types.NAME (sym, r) =>
			    if List.exists (fn n => n=ty) visl (* sym だけではだめ *)
			    then error p ("Type loop error (cyclic definition) "^Symbol.name sym)
			    else (case !r of NONE => error p "Type error"
					   | SOME t => checkLoopItem name t p (ty::visl))
			  | _ => () (* exact type *)
		in case tyl of
		       {name,ty,pos}::tl =>
		       (case Symbol.look (te, name) of
			    NONE => error pos "Type system error"
			  | SOME t => checkLoopItem name t pos [];
			checkLoop te tl
		       )
		     | [] => ()
		end
	    val _ = checkDuplicate tyl
	    val tenv2 = analyze_typelist_1st te tyl
	    val _ = analyze_typelist_2nd tenv2 tyl
	    val _ = checkLoop tenv2 tyl
	in {tenv=tenv2, venv=ve} end
and transDecs (ve, te, dl) =
    case dl of
	hd::tl => let val {venv=ve2,tenv=te2} = transDec (ve,te,hd)
		  in transDecs (ve2,te2,tl) end
      | [] => {venv=ve, tenv=te}

fun transProg e =
    let val tenv = Env.base_tenv
	val venv = Env.base_venv
    in transExp (venv, tenv, e); () end
end

translate.sml

教科書通りにダミーを仕込んでおくだけ。

(* currently dummy module @ chap5 ; will create at chap7 *)
structure Translate =
struct
type exp=unit
end

sources.cm

Group is 
absyn.sml
errormsg.sml
table.sig
table.sml
symbol.sml
parse.sml
tiger.lex
tiger.grm
semant.sml
translate.sml
env.sml
types.sml
$/basis.cm
$/smlnj-lib.cm
$/ml-yacc-lib.cm

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup Referer   Help   RSS of recent changes
Last-modified: (4843d)