diff --git a/hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala b/hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala index ea48cfe3b..55a39f805 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/bbml/bbML.scala @@ -30,11 +30,11 @@ final case class BbCtx( def +=(p: Symbol -> GeneralType): Unit = env += p._1.uid -> p._2 def get(sym: Symbol): Option[GeneralType] = env.get(sym.uid) orElse parent.dlof(_.get(sym))(None) def *=(cls: ClassDef): Unit = clsDefs += cls.sym.id.name -> cls - def getCls(name: Str): Option[ClassSymbol] = + def getCls(name: Str): Option[TypeSymbol] = for elem <- ctx.get(name) sym <- elem.symbol - cls <- sym.asCls + cls <- sym.asTpe yield cls def &=(p: (Symbol, Type, InfVar)): Unit = env += p._1.uid -> BbCtx.varTy(p._2, p._3)(using this) @@ -123,12 +123,12 @@ class BBTyper(using elState: Elaborator.State, tl: TL): genPolyType(tvs, typeAndSubstType(body, pol)) case Term.TyApp(cls, targs) => // log(s"Type application: ${cls.nme} with ${targs}") - cls.symbol.flatMap(_.asCls) match - case S(clsSym) => - if clsSym.nme === "Any" then Top - else if clsSym.nme === "Nothing" then Bot + cls.symbol.flatMap(_.asTpe) match + case S(tpeSym) => + if tpeSym.nme === "Any" then Top + else if tpeSym.nme === "Nothing" then Bot else - val defn = clsSym.defn.get + val defn = tpeSym.defn.get if targs.length != defn.tparams.length then error(msg"Type arguments do not match class definition" -> ty.toLoc :: Nil) val ts = defn.tparams.lazyZip(targs).map: (tp, t) => @@ -143,7 +143,7 @@ class BBTyper(using elState: Elaborator.State, tl: TL): case S(false) => Wildcard.in(ta) case S(true) => Wildcard.out(ta) case N => ta - ClassLikeType(clsSym, ts) + ClassLikeType(tpeSym, ts) case N => error(msg"Not a valid class: ${cls.describe}" -> cls.toLoc :: Nil) case Neg(rhs) => @@ -151,9 +151,9 @@ class BBTyper(using elState: Elaborator.State, tl: TL): case CompType(lhs, rhs, pol) => Type.mkComposedType(typeMonoType(lhs), typeMonoType(rhs), pol) case _ => - ty.symbol.flatMap(_.asCls) match - case S(cls: ClassSymbol) => typeAndSubstType(Term.TyApp(ty, Nil), pol) - case _ => error(msg"${ty.toString} is not a valid type" -> ty.toLoc :: Nil) // TODO + ty.symbol.flatMap(_.asTpe) match + case S(cls: (ClassSymbol | TypeAliasSymbol)) => typeAndSubstType(Term.TyApp(ty, Nil), pol) + case _ => error(msg"${ty.symbol.get.getClass.toString()} is not a valid type" -> ty.toLoc :: Nil) // TODO private def genPolyType(tvs: Ls[QuantVar], body: => GeneralType)(using ctx: BbCtx, cctx: CCtx) = val bds = tvs.map: diff --git a/hkmc2/shared/src/main/scala/hkmc2/bbml/types.scala b/hkmc2/shared/src/main/scala/hkmc2/bbml/types.scala index 7abddb4d4..048dfa735 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/bbml/types.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/bbml/types.scala @@ -209,7 +209,7 @@ object BasicType: case ty :: Nil => ty case ty :: tys => ComposedType(ty, inter(tys), false) -case class ClassLikeType(name: ClassSymbol | ModuleSymbol, targs: Ls[TypeArg]) extends BasicType with CachedNorm[ClassLikeType]: +case class ClassLikeType(name: TypeSymbol | ModuleSymbol, targs: Ls[TypeArg]) extends BasicType with CachedNorm[ClassLikeType]: def mkNorm(using TL): ClassLikeType = ClassLikeType(name, targs.map: diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala index 1b2451b30..1289388ad 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala @@ -44,8 +44,8 @@ abstract class Symbol extends Located: mem.alsTree.map(_.symbol.asInstanceOf[TypeAliasSymbol]) case _ => N - def asClsLike = asCls orElse asMod - def asTpe = asCls orElse asAls + def asClsLike: Opt[ClassSymbol | ModuleSymbol] = asCls orElse asMod + def asTpe: Opt[TypeSymbol] = asCls orElse asAls override def equals(x: Any): Bool = x match case that: Symbol => uid === that.uid @@ -162,7 +162,7 @@ class ModuleSymbol(val tree: Tree.TypeDef, val id: Tree.Ident) def toLoc: Option[Loc] = id.toLoc // TODO track source tree of module here override def toString: Str = s"module:${id.name}" -class TypeAliasSymbol(val id: Tree.Ident) extends MemberSymbol: +class TypeAliasSymbol(val id: Tree.Ident) extends MemberSymbol[TypeDef]: def nme = id.name def toLoc: Option[Loc] = id.toLoc // TODO track source tree of type alias here override def toString: Str = s"module:${id.name}" diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala index 967b3d08d..1e4e4cbb4 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala @@ -212,7 +212,10 @@ sealed abstract class Definition extends Declaration with Statement sealed trait Companion extends Definition -sealed abstract class ClassLikeDef extends Definition: +sealed abstract class TypeLikeDef extends Definition: + val tparams: Ls[TyParam] + +sealed abstract class ClassLikeDef extends TypeLikeDef: val owner: Opt[InnerSymbol] val sym: MemberSymbol[? <: ClassLikeDef] val paramsOpt: Opt[Ls[Param]] @@ -269,7 +272,7 @@ case class TypeDef( tparams: Ls[TyParam], rhs: Opt[Term], companion: Opt[Companion] -) extends Definition +) extends TypeLikeDef // TODO Store optional source locations for the flags instead of booleans diff --git a/hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala b/hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala index 24526a0bf..81f7f44f5 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala @@ -30,7 +30,8 @@ class Keyword( def assumeLeftPrec: Int = leftPrec.getOrElse(lastWords(s"$this does not have left precedence")) def assumeRightPrec: Int = rightPrec.getOrElse(lastWords(s"$this does not have right precedence")) def leftPrecOrMin: Int = leftPrec.getOrElse(Int.MinValue) - def rightPrecOrMax: Int = rightPrec.getOrElse(Int.MaxValue) + def rightPrecOrMin: Int = rightPrec.getOrElse(Int.MinValue) + // def rightPrecOrMax: Int = rightPrec.getOrElse(Int.MaxValue) override def toString: Str = s"keyword '$name'" object Keyword: diff --git a/hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala b/hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala index 7d22dcbdb..0a6873916 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala @@ -256,15 +256,17 @@ object ParseRule: Kw(`type`): ParseRule("type alias declaration"): Expr( - ParseRule("type alias head"): + ParseRule("type alias head")( Kw(`=`): ParseRule("type alias declaration equals sign"): Expr( ParseRule("type alias declaration right-hand side")( End(()) ) - ) { (rhs, _) => rhs } - ) { (lhs, rhs) => TypeDef(Als, lhs, S(rhs), N) }, + ) { case (rhs, ()) => S(rhs) }, + End(N), + ) + ) { (lhs, rhs) => TypeDef(Als, lhs, rhs, N) }, Kw(`class`)(typeDeclBody(Cls)), Kw(`trait`)(typeDeclBody(Trt)), Kw(`module`)(typeDeclBody(Mod)), diff --git a/hkmc2/shared/src/main/scala/hkmc2/syntax/Parser.scala b/hkmc2/shared/src/main/scala/hkmc2/syntax/Parser.scala index bd557bf39..0b37b50db 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/syntax/Parser.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/syntax/Parser.scala @@ -357,7 +357,7 @@ abstract class Parser( prefixRules.kwAlts.get(id.name) match case S(subRule) => // parse(subRule) - val e = exprCont(parseRule(kw.rightPrecOrMax, subRule).getOrElse(errExpr), prec, false) + val e = exprCont(parseRule(kw.rightPrecOrMin, subRule).getOrElse(errExpr), prec, false) parseRule(prec, exprAlt.rest).map(res => exprAlt.k(e, res)) case N => tryEmpty(tok, loc) @@ -489,7 +489,7 @@ abstract class Parser( case (QUOTE, l) :: (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ => consume consume - val rhs = effectfulRhs(kw.rightPrecOrMax) + val rhs = effectfulRhs(kw.rightPrecOrMin) val lhs = bk match case Round => Tup(ps) case Square => TyTup(ps) @@ -498,7 +498,7 @@ abstract class Parser( prec, allowNewlines = true) case (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ => consume - val rhs = effectfulRhs(kw.rightPrecOrMax) + val rhs = effectfulRhs(kw.rightPrecOrMin) val lhs = bk match case Round => Tup(ps) case Square => TyTup(ps) @@ -624,7 +624,7 @@ abstract class Parser( prefixRules.kwAlts.get(kw.name) match case S(subRule) => consume - val rhs = parseRule(kw.rightPrecOrMax, subRule).getOrElse(errExpr) + val rhs = parseRule(kw.rightPrecOrMin, subRule).getOrElse(errExpr) Tree.Empty().withLoc(S(loc)) -> rhs case N => lastWords(s"missing the parse rule for `${kw.name}`") case (tok @ IDENT(opStr, true), loc) :: _ if opPrec(opStr)._1 > 0 => @@ -654,7 +654,7 @@ abstract class Parser( case _ :: (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ if kw.leftPrecOrMin > prec => consume consume - val rhs = effectfulRhs(kw.rightPrecOrMax) + val rhs = effectfulRhs(kw.rightPrecOrMin) exprCont(Quoted(InfixApp(PlainTup(acc), kw, Unquoted(rhs))), prec, allowNewlines) case _ :: (br @ BRACKETS(Round, toks), loc) :: _ => consume @@ -700,7 +700,7 @@ abstract class Parser( // ??? case (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ if kw.leftPrecOrMin > prec => consume - val rhs = effectfulRhs(kw.rightPrecOrMax) + val rhs = effectfulRhs(kw.rightPrecOrMin) val res = acc match case _ => InfixApp(PlainTup(acc), kw, rhs) exprCont(res, prec, allowNewlines) @@ -918,8 +918,8 @@ abstract class Parser( ??? case _ => if verbose then printDbg("$ parsing the right-hand side") - val rhs = expr(kw.rightPrecOrMax) - parseRule(kw.rightPrecOrMax, exprAlt.rest).map: rest => + val rhs = expr(kw.rightPrecOrMin) + parseRule(kw.rightPrecOrMin, exprAlt.rest).map: rest => exprCont(exprAlt.k(rhs, rest)(acc), prec, allowNewlines) // FIXME prec?? .getOrElse(errExpr) case N => diff --git a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls index fc4f816ba..8e08d16e7 100644 --- a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls +++ b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls @@ -1,12 +1,13 @@ -declare class Any +declare type Any +declare type Nothing + declare class Object +declare class Bool declare class Int declare class Num declare class Str -declare class Bool -declare class Nothing declare class Error(msg) declare module String @@ -21,10 +22,10 @@ declare val fs // TODO: rm -fun log: (Any) -> () +declare fun log: (Any) -> () -fun error: Nothing +declare fun error: Nothing -fun concat: (Str, Str) -> Str +declare fun concat: (Str, Str) -> Str