Skip to content

Llir improvement #292

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

Merged
merged 96 commits into from
Apr 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
986a3cf
Copy files to new sub project
waterlens Nov 15, 2024
9244325
Initial Llir builder for `Block`
waterlens Jan 7, 2025
78c9ab5
Resolve classes without methods
waterlens Jan 8, 2025
c39293d
Improve pretty printer
waterlens Jan 8, 2025
a571f82
Add support for ctor app and public fields in the class
waterlens Jan 8, 2025
b189682
Add options for cpp backend
waterlens Jan 9, 2025
b124738
Minor improvements from meeting
LPTK Jan 10, 2025
2501860
Fill blank lines
waterlens Jan 14, 2025
42cffaa
Remove the extra blank line
waterlens Jan 14, 2025
8ba879e
Remove unused context
waterlens Jan 14, 2025
f577445
Add trailing newlines at the end of files
waterlens Jan 14, 2025
6dc0130
Use new pretty printer
waterlens Jan 14, 2025
63bada9
Support instantiate
waterlens Jan 14, 2025
1c267a5
Generate necessary errors
waterlens Jan 15, 2025
f243486
Update names of the flags
waterlens Jan 15, 2025
8f57a4e
Add the interpreter
waterlens Jan 15, 2025
72f817d
Add the compiler host
waterlens Jan 15, 2025
35f7346
Fix
waterlens Jan 15, 2025
7ff48a7
Add wcpp option; Change bool implementation
waterlens Jan 16, 2025
9a41b6a
Try with new CI/nix versions
LPTK Jan 16, 2025
b6eb77e
Fix silly path
waterlens Jan 16, 2025
46f7600
Merge remote-tracking branch 'upstream/hkmc2' into hkmc2-llir
waterlens Jan 16, 2025
376ad91
Add some problematic examples
LPTK Jan 16, 2025
a46ba4e
stop early; fix wrong ctx passing
waterlens Jan 16, 2025
16f2cf8
Merge remote-tracking branch 'upstream/hkmc2' into hkmc2-llir
waterlens Jan 21, 2025
ebdaa5b
Save
waterlens Jan 21, 2025
6f3fca3
fixed freeVars; prototype support of methods
waterlens Feb 4, 2025
ef46ca5
Merge remote-tracking branch 'upstream/hkmc2' into hkmc2-llir
waterlens Feb 4, 2025
3c580d3
Add methods and higher order functions support
waterlens Feb 5, 2025
8538d7c
support higher order functions with virtual methods
waterlens Feb 5, 2025
e30a11b
Reorganize tests
waterlens Feb 5, 2025
8a7c3b7
fix a bug about continuation; port legacy benchmarks
waterlens Feb 5, 2025
471adf6
add more legacy tests
waterlens Feb 6, 2025
37b3533
add a test
waterlens Feb 6, 2025
1589d99
add more tests
waterlens Feb 6, 2025
0d6b593
WIP save
waterlens Feb 7, 2025
17001b1
fix a name bug
waterlens Feb 11, 2025
013112d
Update
waterlens Feb 18, 2025
e65a51d
get cpp codegen back
waterlens Feb 18, 2025
2f92c41
Define symbols only when necessary
waterlens Feb 19, 2025
29ad4fa
Support curried function
waterlens Feb 19, 2025
ea7628e
Support tuple selection
waterlens Feb 19, 2025
5c0888e
Fix some problems
waterlens Feb 19, 2025
441cfe1
fix a problem on cpp generation
waterlens Feb 19, 2025
57a314c
avoid duplicate symbols over blocks
waterlens Feb 20, 2025
17bd141
compile NofibPrelude.mls
waterlens Feb 20, 2025
66ad4c5
Add builtin stuff
waterlens Feb 20, 2025
cb238d5
Math builtins; String and Lazy support in Cpp backend
waterlens Feb 24, 2025
304ebbc
Fix some subtle bugs; add lazy utils to the prelude
waterlens Feb 27, 2025
951f310
be able to run atom.mls
waterlens Feb 27, 2025
1cb19e9
fix some nofib tests; fix Builder; fix mutual recursion
waterlens Feb 28, 2025
e44e7a0
update
waterlens Feb 28, 2025
e9fde96
fix mimalloc
waterlens Mar 1, 2025
d5d3da9
add secretary
waterlens Mar 2, 2025
98d332b
Programs now contain an entry function rather an entry node
waterlens Mar 3, 2025
52a3ead
Save
waterlens Mar 3, 2025
7e93c30
Save
waterlens Mar 4, 2025
19e7c90
save
waterlens Mar 4, 2025
4372f0d
Save
waterlens Mar 5, 2025
1992589
Add simplification opt
waterlens Mar 6, 2025
cfab5f0
Splitting on the fly (with bugs)
waterlens Mar 6, 2025
6d57e5b
checkout the benchmark for reproduction
waterlens Mar 15, 2025
8284bdc
Merge remote-tracking branch 'upstream/hkmc2' into hkmc2-llir
waterlens Mar 17, 2025
d11259f
Reconcile Lifter and LLIR Builder again
waterlens Mar 18, 2025
81b9be0
Remove the optimizer part
waterlens Mar 20, 2025
3eaa589
Improve code style
waterlens Mar 20, 2025
ae263da
Add missing spaces
waterlens Mar 20, 2025
b16e215
Fix a small mistake
waterlens Mar 20, 2025
b58fd9f
Rename test
waterlens Mar 22, 2025
348168f
Remove unused :global
waterlens Mar 22, 2025
6935fd9
Merge remote-tracking branch 'Mark/hkmc2' into feat-llir
waterlens Mar 22, 2025
68edbfc
Add missing `data`; Fix interpreter on tuple field selection
waterlens Mar 23, 2025
8788e4f
Improve test style
waterlens Mar 29, 2025
8aa2777
Remove more unnecessary outputs
waterlens Mar 29, 2025
4f15cc7
Find some additional missing `data`
waterlens Mar 29, 2025
771909a
Backport the fix to multi-value return value
waterlens Apr 1, 2025
cab9e13
Save
waterlens Apr 4, 2025
c753cb5
Save
waterlens Apr 4, 2025
1d57659
Save
waterlens Apr 4, 2025
a8e1525
Rename
waterlens Apr 4, 2025
b656320
Save
waterlens Apr 4, 2025
77bd997
Save
waterlens Apr 4, 2025
a2a88ca
Don't hack
waterlens Apr 4, 2025
23d69f2
Update
waterlens Apr 4, 2025
c97e5a4
Fix
waterlens Apr 4, 2025
ea575ab
Merge remote-tracking branch 'upstream/hkmc2' into feat-llir
waterlens Apr 8, 2025
f22ec12
fix: free vars on llir
waterlens Apr 11, 2025
a53ff6c
Merge remote-tracking branch 'upstream/hkmc2' into feat-llir
waterlens Apr 11, 2025
58bd65d
misc: sync with upstream
waterlens Apr 11, 2025
de1fd2f
revert part of "misc: sync with upstream"
waterlens Apr 11, 2025
0cf2b00
doc: add comments about builtin class `Lazy`
waterlens Apr 11, 2025
4197bea
Changes from meeting
LPTK Apr 16, 2025
99d8b9a
misc: avoid running cpp tests
waterlens Apr 18, 2025
cf7e036
Don't do hack on absolute path
waterlens Apr 18, 2025
4334c67
Merge remote-tracking branch 'Mark/hkmc2' into feat-llir
waterlens Apr 18, 2025
d3f01ed
Improve LLIR testing and fix a problem in paths
LPTK Apr 22, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ case class CompilationUnit(includes: Ls[Str], decls: Ls[Decl], defs: Ls[Def]):
"HiddenTheseEntities", "True", "False", "Callable", "List", "Cons", "Nil", "Option", "Some", "None", "Pair", "Tuple2", "Tuple3", "Nat", "S", "O"
)
stack_list(defs.filterNot {
case Def.StructDef(name, _, _, _) => hiddenNames.contains(name.stripPrefix("_mls_"))
case d: Def.StructDef => hiddenNames.contains(d.name.stripPrefix("_mls_"))
case _ => false
}.map(_.toDocument))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ final class CppCompilerHost(val auxPath: Str):
return

output("Execution succeeded: ")
for line <- stdout do output(line)
for line <- stdout do output(line)
25 changes: 13 additions & 12 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,27 +120,24 @@ sealed abstract class Block extends Product with AutoLocated:
(bod.freeVars - lhs) ++ rst.freeVars ++ hdr.flatMap(_.freeVars)
case End(msg) => Set.empty

// TODO: freeVarsLLIR skips `fun` and `cls` in `Call` and `Instantiate` respectively, which is needed in some
// other places. However, adding them breaks some LLIR tests. Supposedly, once the IR uses the new symbol system,
// this should no longer happen. This version should be removed once that is resolved.
lazy val freeVarsLLIR: Set[Local] = this match
case Match(scrut, arms, dflt, rest) =>
scrut.freeVarsLLIR ++ dflt.toList.flatMap(_.freeVarsLLIR) ++ rest.freeVarsLLIR
++ arms.flatMap:
(pat, arm) => arm.freeVarsLLIR -- pat.freeVars
(pat, arm) => arm.freeVarsLLIR -- pat.freeVarsLLIR
case Return(res, implct) => res.freeVarsLLIR
case Throw(exc) => exc.freeVarsLLIR
case Label(label, body, rest) => (body.freeVarsLLIR - label) ++ rest.freeVarsLLIR
case Break(label) => Set(label)
case Continue(label) => Set(label)
case Break(label) => Set.empty
case Continue(label) => Set.empty
case Begin(sub, rest) => sub.freeVarsLLIR ++ rest.freeVarsLLIR
case TryBlock(sub, finallyDo, rest) => sub.freeVarsLLIR ++ finallyDo.freeVarsLLIR ++ rest.freeVarsLLIR
case Assign(lhs, rhs, rest) => Set(lhs) ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
case Assign(lhs, rhs, rest) => rhs.freeVarsLLIR ++ (rest.freeVarsLLIR - lhs)
case AssignField(lhs, nme, rhs, rest) => lhs.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => lhs.freeVarsLLIR ++ fld.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR
case Define(defn, rest) => defn.freeVarsLLIR ++ rest.freeVarsLLIR
case Define(defn, rest) => defn.freeVarsLLIR ++ (rest.freeVarsLLIR - defn.sym)
case HandleBlock(lhs, res, par, args, cls, hdr, bod, rst) =>
(bod.freeVarsLLIR - lhs) ++ rst.freeVarsLLIR ++ hdr.flatMap(_.freeVars)
(bod.freeVarsLLIR - lhs) ++ rst.freeVarsLLIR ++ hdr.flatMap(_.freeVarsLLIR)
case End(msg) => Set.empty

lazy val subBlocks: Ls[Block] = this match
Expand Down Expand Up @@ -385,8 +382,8 @@ final case class Handler(
params: Ls[ParamList],
body: Block,
):
lazy val freeVarsLLIR: Set[Local] = body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym - resumeSym
lazy val freeVars: Set[Local] = body.freeVars -- params.flatMap(_.paramSyms) - sym - resumeSym
lazy val freeVarsLLIR: Set[Local] = body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym - resumeSym

/* Represents either unreachable code (for functions that must return a result)
* or the end of a non-returning function or a REPL block */
Expand Down Expand Up @@ -446,9 +443,13 @@ sealed abstract class Result extends AutoLocated:
case Value.Rcd(args) => args.flatMap(arg => arg.idx.fold(Set.empty)(_.freeVars) ++ arg.value.freeVars).toSet

lazy val freeVarsLLIR: Set[Local] = this match
case Call(fun, args) => args.flatMap(_.value.freeVarsLLIR).toSet
case Instantiate(cls, args) => args.flatMap(_.freeVarsLLIR).toSet
case Call(fun, args) => fun.freeVarsLLIR ++ args.flatMap(_.value.freeVarsLLIR).toSet
case Instantiate(cls, args) => cls.freeVarsLLIR ++ args.flatMap(_.freeVarsLLIR).toSet
case Select(qual, name) => qual.freeVarsLLIR
case Value.Ref(l: (BuiltinSymbol | TopLevelSymbol | ClassSymbol | TermSymbol)) => Set.empty
case Value.Ref(l: MemberSymbol[?]) => l.defn match
case Some(d: ClassLikeDef) => Set.empty
case _ => Set(l)
case Value.Ref(l) => Set(l)
case Value.This(sym) => Set.empty
case Value.Lit(lit) => Set.empty
Expand Down
2 changes: 1 addition & 1 deletion hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Printer:
.map{ case (c, b) => doc"${case_doc(c)} => #{ # ${mkDocument(b)} #} " }
.mkDocument(sep = doc" # ")
val docDefault = dflt.map(mkDocument).getOrElse(doc"")
doc"match ${mkDocument(scrut)} #{ # ${docCases} # else #{ # ${docDefault} #} #} # in # ${mkDocument(rest)} "
doc"match ${mkDocument(scrut)} #{ # ${docCases} # else #{ # ${docDefault} #} #} # in # ${mkDocument(rest)}"
case Return(res, implct) => doc"return ${mkDocument(res)}"
case Throw(exc) => doc"throw ${mkDocument(exc)}"
case Label(label, body, rest) =>
Expand Down
40 changes: 21 additions & 19 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/cpp/Ast.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package hkmc2.codegen.cpp
package hkmc2
package codegen.cpp

import mlscript._
import mlscript.utils._
import mlscript.utils.shorthands._

import hkmc2.Message.MessageContext
import hkmc2.document._

import scala.language.implicitConversions

import document._

private def raw(x: String): Document = doc"$x"
given Conversion[String, Document] = x => doc"$x"

Expand Down Expand Up @@ -130,14 +129,13 @@ enum Expr:
case Unary(op: Str, expr: Expr)
case Binary(op: Str, lhs: Expr, rhs: Expr)
case Initializer(exprs: Ls[Expr])
case Constructor(name: Str, init: Expr)

def toDocument: Document =
def aux(x: Expr): Document = x match
case Var(name) => name
case IntLit(value) => value.toString
case DoubleLit(value) => value.toString
case StrLit(value) => s"\"$value\"" // need more reliable escape utils
case StrLit(value) => value.escaped
case CharLit(value) => value.toInt.toString
case Call(func, args) =>
doc"${func.toDocument}(${Expr.toDocuments(args, sep = ", ")})"
Expand All @@ -151,8 +149,6 @@ enum Expr:
doc"(${lhs.toDocument} $op ${rhs.toDocument})"
case Initializer(exprs) =>
doc"{${Expr.toDocuments(exprs, sep = ", ")}}"
case Constructor(name, init) =>
doc"$name(${init.toDocument})"
aux(this)

case class CompilationUnit(includes: Ls[Str], decls: Ls[Decl], defs: Ls[Def]):
Expand All @@ -161,57 +157,63 @@ case class CompilationUnit(includes: Ls[Str], decls: Ls[Decl], defs: Ls[Def]):
def toDocumentWithoutHidden: Document =
val hiddenNames: Set[Str] = Set()
defs.filterNot {
case Def.StructDef(name, _, _, _) => hiddenNames.contains(name.stripPrefix("_mls_"))
case Def.StructDef(name, _, _, _, _) => hiddenNames.contains(name.stripPrefix("_mls_"))
case _ => false
}.map(_.toDocument).mkDocument(doc" # ")

enum Decl:
case StructDecl(name: Str)
case EnumDecl(name: Str)
case FuncDecl(ret: Type, name: Str, args: Ls[Type])
case FuncDecl(ret: Type, name: Str, args: Ls[Type], isOverride: Bool, isVirtual: Bool)
case VarDecl(name: Str, typ: Type)

def toDocument: Document =
def aux(x: Decl): Document = x match
case StructDecl(name) => doc"struct $name;"
case EnumDecl(name) => doc"enum $name;"
case FuncDecl(ret, name, args) =>
doc"${ret.toDocument()} $name(${Type.toDocuments(args, sep = ", ")});"
case FuncDecl(ret, name, args, or, virt) =>
val docVirt = (if virt then doc"virtual " else doc"")
val docSpecRet = ret.toDocument()
val docArgs = Type.toDocuments(args, sep = ", ")
val docOverride = if or then doc" override" else doc""
doc"$docVirt$docSpecRet $name($docArgs)$docOverride;"
case VarDecl(name, typ) =>
doc"${typ.toDocument()} $name;"
aux(this)

enum Def:
case StructDef(name: Str, fields: Ls[(Str, Type)], inherit: Opt[Ls[Str]], methods: Ls[Def] = Ls.empty)
case StructDef(name: Str, fields: Ls[(Str, Type)], inherit: Opt[Ls[Str]], methods: Ls[Def], methodsDecl: Ls[Decl])
case EnumDef(name: Str, fields: Ls[(Str, Opt[Int])])
case FuncDef(specret: Type, name: Str, args: Ls[(Str, Type)], body: Stmt.Block, or: Bool = false, virt: Bool = false)
case FuncDef(specret: Type, name: Str, args: Ls[(Str, Type)], body: Stmt.Block, isOverride: Bool, isVirtual: Bool, in_scope: Opt[Str])
case VarDef(typ: Type, name: Str, init: Opt[Expr])
case RawDef(raw: Str)

def toDocument: Document =
def aux(x: Def): Document = x match
case StructDef(name, fields, inherit, defs) =>
case StructDef(name, fields, inherit, defs, decls) =>
val docFirst = doc"struct $name${inherit.fold(doc"")(x => doc": public ${x.mkDocument(doc", ")}")} {"
val docFields = fields.map {
case (name, typ) => doc"${typ.toDocument()} $name;"
}.mkDocument(doc" # ")
val docDefs = defs.map(_.toDocument).mkDocument(doc" # ")
val docDecls = decls.map(_.toDocument).mkDocument(doc" # ")
val docLast = "};"
doc"$docFirst #{ # $docFields # $docDefs #} # $docLast"
doc"$docFirst #{ # $docFields # $docDefs # $docDecls #} # $docLast"
case EnumDef(name, fields) =>
val docFirst = doc"enum $name {"
val docFields = fields.map {
case (name, value) => value.fold(s"$name")(x => s"$name = $x")
}.mkDocument(doc" # ")
val docLast = "};"
doc"$docFirst #{ # $docFields #} # $docLast"
case FuncDef(specret, name, args, body, or, virt) =>
case FuncDef(specret, name, args, body, or, virt, scope) =>
val docVirt = (if virt then doc"virtual " else doc"")
val docSpecRet = specret.toDocument()
val docArgs = Type.toDocuments(args, sep = ", ")
val docOverride = if or then doc" override" else doc""
val docBody = body.toDocument
doc"$docVirt$docSpecRet $name($docArgs)$docOverride ${body.toDocument}"
val docScope = scope.fold(doc"")(x => doc"$x::")
doc"$docVirt$docSpecRet $docScope$name($docArgs)$docOverride ${body.toDocument}"
case VarDef(typ, name, init) =>
val docTyp = typ.toDocument()
val docInit = init.fold(raw(""))(x => doc" = ${x.toDocument}")
Expand Down
Loading
Loading