Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Type Alias and Fix Record Type Translation in ts2mls #143

Merged
merged 19 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion shared/src/main/scala/mlscript/NewLexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ object NewLexer {
"trait",
"interface",
"new",
"namespace"
"namespace",
"type"
)

def printToken(tl: TokLoc): Str = tl match {
Expand Down
2 changes: 1 addition & 1 deletion shared/src/main/scala/mlscript/NewParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], raiseFun: D
expr(0) :: parents(COMMA)
case _ => Nil
}
val ps = parents(KEYWORD(":"))
val ps = parents(if (kind === Als) KEYWORD("=") else KEYWORD(":"))
val body = curlyTypingUnit
R(NuTypeDef(kind, tn, tparams, params, ps, body))

Expand Down
10 changes: 7 additions & 3 deletions shared/src/main/scala/mlscript/helpers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -429,17 +429,21 @@ trait TermImpl extends StatementImpl { self: Term =>
case Tup(fields) => Tuple(fields.map(fld => (fld._1, fld._2 match {
case Fld(m, s, v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)
})))
case Bra(rcd, trm) if (!rcd) => trm.toType_!
case Bra(rcd, trm) => trm match {
case _: Rcd => if (rcd) trm.toType_! else throw new NotAType(this)
case _ => if (!rcd) trm.toType_! else throw new NotAType(this)
}
case TyApp(lhs, targs) => lhs.toType_! match {
case p: TypeName => AppliedType(p, targs)
case _ => throw new NotAType(this)
}
case Rcd(fields) => Record(fields.map(fld => (fld._1, fld._2 match {
case Fld(m, s, v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)
})))
// TODO:
// case Rcd(fields) => ???
// case Sel(receiver, fieldName) => ???
// case Let(isRec, name, rhs, body) => ???
// case Blk(stmts) => ???
// case Bra(rcd, trm) => ???
// case Asc(trm, ty) => ???
// case Bind(lhs, rhs) => ???
// case Test(trm, ty) => ???
Expand Down
9 changes: 8 additions & 1 deletion ts2mls/js/src/main/scala/ts2mls/JSWriter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ import mlscript.utils._

class JSWriter(filename: String) {
import JSWriter._
private val out = fs.openSync(filename, "rs+")

// Create an empty file if it does not exists.
if (!fs.existsSync(filename)) fs.writeFileSync(filename, "")

// r+: Open file for reading and writing. An exception occurs if the file does not exist.
// See https://nodejs.org/api/fs.html#file-system-flags to get more details.
private val out = fs.openSync(filename, "r+")

private var fileSize = 0 // how many bytes we've written in the file
private var needTruncate = false

Expand Down
2 changes: 2 additions & 0 deletions ts2mls/js/src/main/scala/ts2mls/TSCompilerInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ object TypeScript {
def isModuleDeclaration(node: js.Dynamic) = ts.isModuleDeclaration(node)
def isArrayTypeNode(node: js.Dynamic) = ts.isArrayTypeNode(node)
def isTupleTypeNode(node: js.Dynamic) = ts.isTupleTypeNode(node)
def isTypeAliasDeclaration(node: js.Dynamic) = ts.isTypeAliasDeclaration(node)

def forEachChild(root: js.Dynamic, func: js.Dynamic => Unit) = ts.forEachChild(root, func)
def createProgram(filenames: Seq[String]) =
Expand Down Expand Up @@ -87,6 +88,7 @@ class TSNodeObject(node: js.Dynamic)(implicit checker: TSTypeChecker) extends TS
lazy val isClassDeclaration = TypeScript.isClassDeclaration(node)
lazy val isInterfaceDeclaration = TypeScript.isInterfaceDeclaration(node)
lazy val isFunctionLike = TypeScript.isFunctionLike(node)
lazy val isTypeAliasDeclaration = TypeScript.isTypeAliasDeclaration(node)

// `TypeScript.isModuleDeclaration` works on both namespaces and modules
// but namespaces are more recommended, so we merely use `isNamespace` here
Expand Down
3 changes: 2 additions & 1 deletion ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class TSNamespace(name: String, parent: Option[TSNamespace]) {
case _: TSClassType => writer.writeln(Converter.convert(mem)(indent))
case TSInterfaceType(name, _, _, _) if (name =/= "") =>
writer.writeln(Converter.convert(mem)(indent))
case _ => writer.writeln(Converter.convert(mem))
case _: TSTypeAlias => writer.writeln(Converter.convert(mem)(indent))
case _ => throw new AssertionError("only functions, classes, interfaces and type alias can be exported.")
}
}
})
Expand Down
16 changes: 12 additions & 4 deletions ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ object TSSourceFile {
else if (obj.isTypeParameter) TSTypeParameter(obj.symbol.escapedName)
else TSPrimitiveType(obj.intrinsicName)

// the function `getMemberType` can't process function/tuple type alias correctly
private def getTypeAlias(tn: TSNodeObject): TSType =
if (tn.isFunctionLike) getFunctionType(tn)
else if (tn.isTupleTypeNode) TSTupleType(getTupleElements(tn.typeNode.typeArguments))
else getObjectType(tn.typeNode)

// get the type of a member in classes/named interfaces/anonymous interfaces
private def getMemberType(node: TSNodeObject): TSType = {
val res: TSType =
Expand All @@ -42,7 +48,7 @@ object TSSourceFile {
else res
}

private def getTypeParametes(node: TSNodeObject): List[TSTypeParameter] =
private def getTypeParameters(node: TSNodeObject): List[TSTypeParameter] =
node.typeParameters.foldLeft(List[TSTypeParameter]())((lst, tp) =>
if (tp.constraint.isUndefined) lst :+ TSTypeParameter(tp.symbol.escapedName, None)
else lst :+ TSTypeParameter(tp.symbol.escapedName, Some(getObjectType(tp.constraint.typeNode)))
Expand All @@ -57,7 +63,7 @@ object TSSourceFile {
lst :+ TSParameterType(p.symbol.escapedName, TSUnionType(getObjectType(p.symbolType), TSPrimitiveType("undefined")))
else lst :+ TSParameterType(p.symbol.escapedName, getObjectType(p.symbolType)))
)
TSFunctionType(pList, getObjectType(node.returnType), getTypeParametes(node))
TSFunctionType(pList, getObjectType(node.returnType), getTypeParameters(node))
}

private def getStructuralType(types: TSTypeArray, isUnion: Boolean): TSType =
Expand Down Expand Up @@ -130,8 +136,8 @@ object TSSourceFile {
private def parseMembers(name: String, node: TSNodeObject, isClass: Boolean): TSType =
if (isClass)
TSClassType(name, getClassMembersType(node.members, false), getClassMembersType(node.members, true),
getTypeParametes(node), getHeritageList(node), getConstructorList(node.members))
else TSInterfaceType(name, getInterfacePropertiesType(node.members), getTypeParametes(node), getHeritageList(node))
getTypeParameters(node), getHeritageList(node), getConstructorList(node.members))
else TSInterfaceType(name, getInterfacePropertiesType(node.members), getTypeParameters(node), getHeritageList(node))

private def parseNamespaceLocals(map: TSSymbolMap)(implicit ns: TSNamespace) =
map.foreach((sym) => {
Expand Down Expand Up @@ -176,6 +182,8 @@ object TSSourceFile {
ns.put(name, parseMembers(name, node, true))
else if (node.isInterfaceDeclaration)
ns.put(name, parseMembers(name, node, false))
else if (node.isTypeAliasDeclaration)
ns.put(name, TSTypeAlias(name, getTypeAlias(node.`type`), getTypeParameters(node)))
else if (node.isNamespace)
parseNamespace(node)

Expand Down
5 changes: 4 additions & 1 deletion ts2mls/js/src/main/scala/ts2mls/types/Converter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ object Converter {
case TSSubstitutionType(base, applied) => s"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s"$res, $s")}>"
case overload @ TSIgnoredOverload(base, _) => s"${convert(base)} ${overload.warning}"
case TSParameterType(name, tp) => s"${name}: ${convert(tp)}"
case TSTypeAlias(name, ori, tp) =>
if (tp.isEmpty) s"${indent}type $name = ${convert(ori)}"
else s"${indent}type $name<${tp.map(t => convert(t)).reduceLeft((s, t) => s"$s, $t")}> = ${convert(ori)}"
}

private def convertRecord(typeName: String, members: Map[String, TSMemberType], typeVars: List[TSTypeParameter],
Expand All @@ -75,7 +78,7 @@ object Converter {
val body = { // members without independent type parameters, translate them directly
val lst = allRecs.filter((s) => !s.isEmpty())
if (lst.isEmpty) "{}"
else if (typeName === "trait ") s"(${lst.reduceLeft((bd, m) => s"$bd$m")})"
else if (typeName === "trait ") s"{${lst.reduceLeft((bd, m) => s"$bd$m")}}"
else s"{\n${lst.reduceLeft((bd, m) => s"$bd$m")}$indent}"
}

Expand Down
2 changes: 2 additions & 0 deletions ts2mls/js/src/main/scala/ts2mls/types/TSType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ case class TSIntersectionType(lhs: TSType, rhs: TSType) extends TSStructuralType
case class TSIgnoredOverload(base: TSFunctionType, name: String) extends TSType {
val warning = s"/* warning: the overload of function $name is not supported yet. */"
}

case class TSTypeAlias(name: String, original: TSType, tp: List[TSType]) extends TSType
8 changes: 4 additions & 4 deletions ts2mls/js/src/test/diff/InterfaceMember.d.mls
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ trait IFoo() {
trait II<T>() {
fun test(x: T): number
}
fun create(): (v: number,)
fun get(x: (t: string,)): string
fun create(): {v: number,}
fun get(x: {t: string,}): string
trait IEvent() {
fun callback(): (number) => unit
}
Expand All @@ -36,5 +36,5 @@ trait Next(): Simple {}
trait TTT<T>() {
fun ttt(x: T): T
}
//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|x|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|x|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|x|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |(|v|#:| |number|,|)|↵|#fun| |get|(|x|#:| |(|t|#:| |string|,|)|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(||)|#:| |(|number|)| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|source|#:| |string|,| |subString|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|index|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|start|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|←|↵|}|
//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (x: number,) -> number; fun c: [] -> () -> ((false,) | (true,)); fun d: [] -> (x: string,) -> unit}; trait II[T](): {fun test: [] -> (x: T,) -> number}; fun create: [] -> () -> (v: number,); fun get: [] -> (x: (t: string,),) -> string; trait IEvent(): {fun callback: [] -> () -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (source: string, subString: string,) -> ((false,) | (true,))}; trait StringArray(): {fun __index: [] -> (index: number,) -> string}; trait Counter(): {fun __call: [] -> (start: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (x: (false,) | (true,),) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (x: T,) -> T}}
//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|x|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|x|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|x|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |{|v|#:| |number|,|}|↵|#fun| |get|(|x|#:| |{|t|#:| |string|,|}|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(||)|#:| |(|number|)| |=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|source|#:| |string|,| |subString|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|index|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|start|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|←|↵|}|
//│ Parsed: {trait IFoo(): {let a: [] -> string; fun b: [] -> (x: number,) -> number; fun c: [] -> () -> ((false,) | (true,)); fun d: [] -> (x: string,) -> unit}; trait II[T](): {fun test: [] -> (x: T,) -> number}; fun create: [] -> () -> {v: number}; fun get: [] -> (x: {t: string},) -> string; trait IEvent(): {fun callback: [] -> () -> number -> unit}; trait SearchFunc(): {fun __call: [] -> (source: string, subString: string,) -> ((false,) | (true,))}; trait StringArray(): {fun __index: [] -> (index: number,) -> string}; trait Counter(): {fun __call: [] -> (start: number,) -> string; let interval: [] -> number; fun reset: [] -> () -> unit}; trait Simple(): {let a: [] -> number; fun b: [] -> (x: (false,) | (true,),) -> string}; trait Simple2[T](): {let abc: [] -> T}; trait Next(): Simple: {}; trait TTT[T](): {fun ttt: [] -> (x: T,) -> T}}
6 changes: 3 additions & 3 deletions ts2mls/js/src/test/diff/Overload.d.mls
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fun g0: ((MutArray<string>) => string) & ((MutArray<object>) => string)
fun db: ((number) => MutArray<number>) & ((object) => MutArray<number>)
class N() {}
fun id: ((M) => unit) & ((N) => unit)
fun tst: (((z: number,)) => (y: string,)) & (((z: (false) | (true),)) => (y: string,))
fun tst: (({z: number,}) => {y: string,}) & (({z: (false) | (true),}) => {y: string,})
fun op: ((number) => ((number) | (undefined)) => unit) & ((number) => (((false) | (true)) | (undefined)) => unit)
fun swap: (((number, string, )) => (number, string, )) & (((string, number, )) => (number, string, ))
fun u: ((((number) | (false)) | (true)) => string) & ((object) => string)
Expand All @@ -22,5 +22,5 @@ class WWW() {
fun F<T>(x: T): anything /* warning: the overload of function F is not supported yet. */
}
fun baz(): anything /* warning: the overload of function baz is not supported yet. */
//│ |#fun| |f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|(|string|)| |=>| |unit|)| |=>| |(|number|)| |=>| |unit|)| |&| |(|(|(|string|)| |=>| |unit|)| |=>| |(|string|)| |=>| |unit|)|↵|#fun| |create|#:| |(|(|number|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|(|false|)| ||| |(|true|)|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |string|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |string|)|↵|#fun| |db|#:| |(|(|number|)| |=>| |MutArray|‹|number|›|)| |&| |(|(|object|)| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|(|M|)| |=>| |unit|)| |&| |(|(|N|)| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|(|z|#:| |number|,|)|)| |=>| |(|y|#:| |string|,|)|)| |&| |(|(|(|z|#:| |(|false|)| ||| |(|true|)|,|)|)| |=>| |(|y|#:| |string|,|)|)|↵|#fun| |op|#:| |(|(|number|)| |=>| |(|(|number|)| ||| |(|undefined|)|)| |=>| |unit|)| |&| |(|(|number|)| |=>| |(|(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|x|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|x|#:| |T|,| |n|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|x|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ((z: number,) -> (y: string,),) & ((z: (false,) | (true,),) -> (y: string,),); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (x: anything,) -> unit; namespace XX(): {fun f: [] -> (x: T, n: anything,) -> string}; class WWW() {fun F: [] -> (x: T,) -> anything}; fun baz: [] -> () -> anything}
//│ |#fun| |f|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|(|number|)| |=>| |string|)| |&| |(|(|string|)| |=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|(|string|)| |=>| |unit|)| |=>| |(|number|)| |=>| |unit|)| |&| |(|(|(|string|)| |=>| |unit|)| |=>| |(|string|)| |=>| |unit|)|↵|#fun| |create|#:| |(|(|number|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|(|false|)| ||| |(|true|)|)| |=>| |unit| |=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|(|MutArray|‹|string|›|)| |=>| |string|)| |&| |(|(|MutArray|‹|object|›|)| |=>| |string|)|↵|#fun| |db|#:| |(|(|number|)| |=>| |MutArray|‹|number|›|)| |&| |(|(|object|)| |=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|(|M|)| |=>| |unit|)| |&| |(|(|N|)| |=>| |unit|)|↵|#fun| |tst|#:| |(|(|{|z|#:| |number|,|}|)| |=>| |{|y|#:| |string|,|}|)| |&| |(|(|{|z|#:| |(|false|)| ||| |(|true|)|,|}|)| |=>| |{|y|#:| |string|,|}|)|↵|#fun| |op|#:| |(|(|number|)| |=>| |(|(|number|)| ||| |(|undefined|)|)| |=>| |unit|)| |&| |(|(|number|)| |=>| |(|(|(|false|)| ||| |(|true|)|)| ||| |(|undefined|)|)| |=>| |unit|)|↵|#fun| |swap|#:| |(|(|(|number|,| |string|,| |)|)| |=>| |(|number|,| |string|,| |)|)| |&| |(|(|(|string|,| |number|,| |)|)| |=>| |(|number|,| |string|,| |)|)|↵|#fun| |u|#:| |(|(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| |=>| |string|)| |&| |(|(|object|)| |=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|x|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#namespace| |XX| |{|→|#fun| |f|‹|T|›|(|x|#:| |T|,| |n|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|x|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|
//│ Parsed: {fun f: [] -> (number -> string,) & (string -> string,); class M() {let foo: [] -> (number -> string,) & (string -> string,)}; fun app: [] -> ((string -> unit) -> number -> unit,) & ((string -> unit) -> string -> unit,); fun create: [] -> (number -> unit -> ((false,) | (true,)),) & (((false,) | (true,)) -> unit -> ((false,) | (true,)),); fun g0: [] -> (MutArray[string] -> string,) & (MutArray[object] -> string,); fun db: [] -> (number -> MutArray[number],) & (object -> MutArray[number],); class N() {}; fun id: [] -> (M -> unit,) & (N -> unit,); fun tst: [] -> ({z: number} -> {y: string},) & ({z: (false,) | (true,)} -> {y: string},); fun op: [] -> (number -> ((number,) | (undefined,)) -> unit,) & (number -> (((false,) | (true,),) | (undefined,)) -> unit,); fun swap: [] -> ((number, string,) -> (number, string,),) & ((string, number,) -> (number, string,),); fun u: [] -> ((((number,) | (false,),) | (true,)) -> string,) & (object -> string,); fun doSome: [] -> (x: anything,) -> unit; namespace XX(): {fun f: [] -> (x: T, n: anything,) -> string}; class WWW() {fun F: [] -> (x: T,) -> anything}; fun baz: [] -> () -> anything}
Loading