tiger book読書記録 chapter 5

Oct 9, 2018
chapter 5本文を読む.symbol table, binding, type checkが書いてある.chap 4でASTを作った後のstepである.本文はこうすれば意味解析が実装できると書いてある.プログラム演習はそれに沿って実装することになる.chap4の結果からfileをcopyして準備した.明日から意味解析を実装する.smlに慣れていないと実装が大変そうなsymbol table, binding tableは提供されているので素直に残りを埋めるだけか.

Oct 10, 2018
translate.sml. これは本文中に載っているものそのまま.後の章で実装する為のものでからの実装.

signature TRANSLATE =
sig
    type exp;
end

structure Translate : TRANSLATE =
struct
    type exp = unit;
end

env.sml.本文にsignatureが載っているのでstructureを実装する.type accessを何に使うか不明.取り敢えずtype access = intとしておいた.必要になったら変更しよう.

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

    structure A = Absyn;
    structure T = Types;

    type access = int; (* ??? *)
    type ty = T.ty;

    datatype enventry = VarEntry of {ty: ty}
                      | FunEntry of {formals: ty list, result: ty};

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

    val predefined_types = [("int", T.INT),
                            ("nil", T.NIL),
                            ("string", T.STRING),
                            ("unit", T.UNIT)];
    val predefined_funs = [
        ("print", [T.INT], T.UNIT),
        ("flush", nil : ty list, T.UNIT),
        ("getchar", nil : ty list, T.STRING),
        ("ord", [T.STRING], T.INT),
        ("chr", [T.INT], T.STRING),
        ("size", [T.STRING], T.INT),
        ("substring", [T.INT, T.INT, T.STRING], T.STRING),
        ("concat", [T.STRING, T.STRING], T.STRING),
        ("not", [T.INT], T.INT),
        ("exit", [T.INT], T.UNIT)];

    fun enter_type ((name, type_ty), table) =
        Symbol.enter (table, Symbol.symbol name, type_ty);
    fun enter_fun ((name, formals, result), table) =
        Symbol.enter (table, Symbol.symbol name,
                      FunEntry {formals=formals, result=result});

    val base_tenv : ty Symbol.table =
        foldl enter_type Symbol.empty predefined_types;
    val base_venv : enventry Symbol.table =
        foldl enter_fun Symbol.empty predefined_funs;
end;

明日からはSemant moduleの実装に入る.

Oct 15, 2018
semant.smlの実装を開始する.本文中のadviseに従って素直に実装することにする.まずはabsyn.smlに従ってpattern matchを用意する.中身の実装はこれから.特に難しいことはないよな.素直に埋めていけばいい筈.

structure A = Absyn;

signature SEMANT =
sig
    type venv;
    type tenv;
    type expty;

    val transProg: A.exp -> unit;

    val transVar: venv * tenv * A.var -> expty;
    val transExp: venv * tenv * A.exp -> expty;
    val transDec: venv * tenv * A.dec -> {venv: venv, tenv: tenv};
    val transTy: tenv * A.ty -> Types.ty;
end;

structure Semant : SEMANT =
struct
    structure T = Types;

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

    exception Semant;

    fun transProg (exp: A.exp): unit =
        let
            val _ = transExp exp;
        in
            ()
        end

    fun checkInt ({exp, ty}, pos) = ();

    (* fun transExp (venv: venv, tenv: tenv, exp: A.exp): expty = *)
    fun transExp (venv, tenv, A.VarExp (var)) =
        transVar (venv, tenv, var)
      | transExp (venv, tenv, NilExp) = {exp=(), ty=T.NIL}
      | transExp (venv, tenv, A.IntExp (i)) = {exp=(), ty=T.INT}
      | transExp (venv, tenv, A.StringExp(str)) = {exp=(), ty=T.STRING}
      | transExp (venv, tenv, A.CallExp{func=sym, args=explist, pos=pos}) =
        let
            val func_sym_opt = lookup (tenv, func);
            val func_sym =
                case func_sym_opt of
                    NONE => raise Semant "undefined function: " ^ (A.name sym)
                  | SOME func_sym => func_sym;
            val fun_result =
                case func_sym of
                    VarEntry{ty=ty} => raise Semant "var is used as fun: " ^ (A.name sym)
                  | FunEntry{result=ty, ...} => ty;
        in
            expty {exp=(), ty=ty}
        end
      | transExp (venv, tenv,
                  A.OpExp {left=left, oper=oper, right=right, pos=pos}) =
        let
        in
            {exp=(), ty=}
        end
      | transExp transExp (
            venv, tenv, A.RecordExp {fiedls=fields_list, typ=sym, pos=pos}) =
        let
        in
            {exp=(), ty=}
        end
      | transExp (venv, tenv, A.SeqExp (seq_list)) =
        let
        in
            {exp=(), ty}
        end
      | transExp (venv, tenv, A.AssignExp {var=var, exp=exp, pos=pos}) =
        let
        in
            {exp=(), ty}
        end
      | transExp (venv, tenv,
                  A.IfExp {test=test_exp, then'=then_exp,
                           else'=NONE, pos=pos}) =
        let
        in
            {exp=(), ty=T.UNIT}
        end
      | transExp (venv, tenv,
                  A.IfExp {test=test_exp, then'=then_exp,
                           else'=SOME else_exp, pos=pos}) =
        let
        in
            {exp=(), ty=}
        end
      | transExp (venv, tenv,
                  A.WhileExp {test=test_exp, body=body_exp, pos=pos})=
        let
        in
            {exp=(), ty=T.UNIT}
        end
      | transExp (venv, tenv,
                  A.ForExp {var=sym, escape=ref esc,
                            lo=lo_exp, hi=hi_exp, body=body_exp, pos=pos}) =
        let
        in
        end
      | transExp (venv, tenv, A.BreakExp (pos)) =
        let
        in
            {exp=(), ty=T.UNIT}
        end
      | transExp (venv, tenv,
                  A.LetExp {desc=desc_list, body=body_exp, pos=pos}) =
        let
        in
            {exp=(), ty=}
        end
      | transExp (venv, tenv,
                  A.ArrayExp {typ=sym, size=size_exp, init=init_exp,
                              pos=pos}) =
        let
        in
            {exp=(), ty=T.UNIT}
        end
    and transVar (venv, tenv, A.SimpleVar (sym, pos)) =
        let
        in
            {exp=(), ty=}
        end
      | transVar (venv, tenv, A.FieldVar (var, sym, pos)) =
        let
        in
            {exp=(), ty=}
        end
      | transVar (venv, tenv, SubscriptVar (var, exp, pos)) =
        let
        in
            {exp=(), ty=}
        end
    and transDec (venv: venv, tenv: tenv, dec: A.dec): {venv: venv, tenv: tenv} = ();
    and transDec (venv, tenv, A.FunctionDec (fundec_list)) =
        let
        in
            {exp=(), ty=}
        end
      | transDec (venv, tenv,
                  A.VarDec {name=sym, escape=ref esc, typ: typ,
                            init=init_exp, pos=pos}) =
        let
        in
        end
      | transDec (venv, tenv, A.TypeDec (ty_list)) =
        let
        in
        end
    and transTy  (tenv, A.NameTy (sym, pos)) =
        let
        in
        end
      | transTy (tenv, A.RecordTy (field_list)) =
        let
        in
        end
      | transTy (tenv, A.ArrayTy (sym, pos)) =
        let
        in
        end;
end;

この記事が気に入ったらサポートをしてみませんか?