暗黙の型変換
暗黙の型変換を修正しました。
ネストした式にも対応しました。
関数呼び出しの型は、呼び出したリターン値の型にしました。
EIdにも型を持たせて、関数の型を入れるようにしました。
package t7; object Main { trait TType case class TFloat() extends TType case class TInt() extends TType case class TNone() extends TType case class TStr() extends TType case class TFun(prms:List[TType],rc:TType) extends TType sealed abstract case class E(t:TType) case class EId(override val t:TType, s:String) extends E(t) case class ECast(override val t:TType, a:E) extends E(t) case class EInt(override val t:TType, a:scala.Int) extends E(t) case class EFloat(override val t:TType, a:Double) extends E(t) case class ECall(override val t:TType, f:E, a:List[E]) extends E(t) def main(argv:Array[String]) { println("*"+f(ECall(TNone(),EId(TNone(),"add"),List(EFloat(TFloat(),1),EInt(TInt(),2))))) println("*"+f(ECall(TNone(),EId(TNone(),"add"),List(EInt(TInt(),1),EInt(TInt(),2))))) println("*"+f(ECall(TNone(),EId(TNone(),"add"), List(ECall(TNone(),EId(TNone(),"add"),List(EFloat(TFloat(), 1),EInt(TInt(),1))),EInt(TInt(),2))))) } def f(e:E):E = e match { case ECast(t,a) => ECast(t, f(a)) case EInt(t,i) => EInt(TInt(), i) case EFloat(t,i) => EFloat(TFloat(), i) case EId(t,a) => EId(t,a) case ECall(t,EId(tid,id),xs1) => val xs = xs1.map(f) // 暗黙の型変換つき型チェック def typeCheck(ts:List[TType],es:List[E]):Option[List[E]] = { (ts,es) match { case (List(),List()) => Some(List()) case (t::ts,e::es) => typeCheck(ts,es) match { case None => None case Some(e2) => val t2 = e match { case ECall(TFun(_,r),_,_) => r case e:E => e.t } if(t==t2) Some(e::e2) else if(implicitConversions.contains(t->t2)) Some(implicitConversions(t->t2)(e)::e2) else None } case _ => None } } // 関数を全て取り出す def fns(funs:List[TFun]):Option[E] = funs match { case List() => None case (i@TFun(l,r))::ls => typeCheck(l, xs) match { case None => fns(ls) case Some(e) => Some(ECall(r, EId(i,id), e)) } } fns(functions(id)) match { case None=> throw new Exception("not found method "+e) case Some(e) => e } } // 関数定義表 var functions = Map[String,List[TFun]]( "add"->List( TFun(List(TInt(),TInt()),TInt()), TFun(List(TStr(),TStr()),TStr()), TFun(List(TFloat(),TFloat()),TFloat()) ) ) // 暗黙の型変換の表 var implicitConversions = Map[(TType,TType),(E)=>E] ( (TInt(),TStr()) -> ((a:E)=>ECast(TStr(),a)), (TFloat(),TStr()) -> ((a:E)=>ECast(TStr(),a)), (TFloat(),TInt()) -> ((a:E)=>ECast(TFloat(),a)) ) }