signature ENV = sig 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 val tlook: ty Symbol.table * Symbol.symbol -> ty option val vlook: enventry Symbol.table * Symbol.symbol -> enventry option end structure Env :> ENV where type ty = Types.ty = struct structure S = Symbol structure T = Types type ty = T.ty datatype enventry = VarEntry of {ty: ty} | FunEntry of {formals: ty list, result: ty} type tenv = ty S.table val baseTypeList = [(S.symbol "int", T.INT), (S.symbol "string", T.STRING), (S.symbol "unit", T.UNIT) ] val base_tenv = S.enterList (S.empty, baseTypeList) fun tlook (tenv: tenv, key: S.symbol): ty option = case S.look (tenv, key) of NONE => S.look (base_tenv, key) | oty => oty type venv = enventry S.table val baseValueList = [(S.symbol "print", FunEntry {formals= [T.STRING], result= T.UNIT}), (S.symbol "flush", FunEntry {formals= [], result= T.UNIT}), (S.symbol "getchar", FunEntry {formals= [], result= T.STRING}), (S.symbol "ord", FunEntry {formals= [T.STRING], result= T.INT}), (S.symbol "chr", FunEntry {formals= [T.INT], result= T.STRING}), (S.symbol "size", FunEntry {formals= [T.STRING], result= T.INT}), (S.symbol "substring", FunEntry {formals= [T.STRING,T.INT,T.INT], result= T.STRING}), (S.symbol "concat", FunEntry {formals= [T.STRING,T.STRING], result= T.STRING}), (S.symbol "not", FunEntry {formals= [T.INT], result= T.INT}), (S.symbol "exit", FunEntry {formals= [T.INT], result= T.UNIT})] val base_venv = S.enterList (S.empty, baseValueList) fun vlook (venv: venv, key: S.symbol): enventry option = case S.look (venv, key) of NONE => S.look (base_venv, key) | oentry => oentry end