Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
222 commits
Select commit Hold shift + click to select a range
9c3cea1
Add `staged` keyword
ChingLongTin Sep 30, 2025
2711dd9
remove comments
yeungsinchun Sep 30, 2025
a20f7ce
Merge pull request #1 from ChingLongTin/staged-syntax
ChingLongTin Sep 30, 2025
47124f9
Merge branch 'hkust-taco:hkmc2' into hkmc2
ChingLongTin Oct 4, 2025
7edc9b6
draft out Block.mls
ChingLongTin Oct 4, 2025
becf900
switch from List to Array
ChingLongTin Oct 22, 2025
acc97a2
make constructor fields public
ChingLongTin Oct 22, 2025
c337fb3
remove type alias for Symbol
ChingLongTin Oct 22, 2025
03e24d6
fix whitespace issues
ChingLongTin Oct 22, 2025
866d68c
simplify ParamList representation
ChingLongTin Oct 23, 2025
abbb517
add more constructors to Block.mls
ChingLongTin Oct 28, 2025
5c275d2
remove unnecessary fields
ChingLongTin Oct 28, 2025
1ff0f5a
Merge pull request #2 from ChingLongTin/block-mls
ChingLongTin Oct 28, 2025
ac3a2f3
Merge pull request #3 from hkust-taco/hkmc2
ChingLongTin Oct 28, 2025
539bca3
Instrumentation progress following formalization
ChingLongTin Oct 29, 2025
3d43c81
Merge branch 'hkmc2' into instrument
ChingLongTin Oct 29, 2025
9298f36
add Block.mls
ChingLongTin Oct 31, 2025
4796cad
Add Block.mls into DiffMaker and prepare the function for lowering
yeungsinchun Oct 28, 2025
b072e4a
add block.mjs also in MLsCompiler
yeungsinchun Oct 30, 2025
35106c0
lower 'staged' annotations to Block and add display of 'staged' anno…
yeungsinchun Oct 30, 2025
4efccdf
amend! Add Block.mls into DiffMaker and prepare the function for lowe…
ChingLongTin Oct 31, 2025
f9ad612
clean up Syntax.mls
ChingLongTin Oct 31, 2025
f763b03
fiddle with printing staged keyword in FunDefn
ChingLongTin Oct 31, 2025
85f86c3
revert whitespace
ChingLongTin Oct 31, 2025
a39765e
revert change to printing
ChingLongTin Oct 31, 2025
ee681c9
move isStaged inside Fun
ChingLongTin Oct 31, 2025
f77c44c
more formatting fixes
ChingLongTin Oct 31, 2025
9c4c754
add new symbols to Elaborator
ChingLongTin Oct 31, 2025
4e5b281
remove Shape and Pattern
ChingLongTin Oct 31, 2025
d3aa471
rework function signatures
ChingLongTin Oct 31, 2025
b251526
clean up Block.mls
ChingLongTin Oct 31, 2025
84730bf
add Shape.mls
ChingLongTin Oct 31, 2025
f44b167
copy over more rules
ChingLongTin Oct 31, 2025
dcb0ed6
remove import of block inside MLsCompiler
yeungsinchun Oct 31, 2025
bfac96d
update diff test result (for the staged annotation)
yeungsinchun Oct 31, 2025
a81c0e9
fix importing for Block.mls
ChingLongTin Nov 1, 2025
4b0fa45
draft ruleInst
ChingLongTin Nov 1, 2025
3761d19
generalize recursion
ChingLongTin Nov 1, 2025
3ca8a98
add more rules
ChingLongTin Nov 1, 2025
71d5df3
remove length parameter from Shape.Arr
ChingLongTin Nov 1, 2025
cca32c6
stub all current rules
ChingLongTin Nov 1, 2025
ea13fe3
change transform* signature
ChingLongTin Nov 1, 2025
47919c4
change staged* to mls*
ChingLongTin Nov 1, 2025
217fb90
simplify getShape, getCode
ChingLongTin Nov 1, 2025
3827db5
reword transformArgs
ChingLongTin Nov 2, 2025
2d9c3d2
remove extractResult
ChingLongTin Nov 2, 2025
c5be8ec
introduce StagedPath
ChingLongTin Nov 2, 2025
b4eaf5c
introduce Shape
ChingLongTin Nov 2, 2025
2563eca
link to functions in Shape.mls
ChingLongTin Nov 2, 2025
edd7436
move function
ChingLongTin Nov 2, 2025
c17c3e1
implement more rules
ChingLongTin Nov 2, 2025
369195f
add stubs for function instrumentation
ChingLongTin Nov 2, 2025
ded7260
add instrumentation context
ChingLongTin Nov 2, 2025
5e08d17
refactor transformArgs
ChingLongTin Nov 2, 2025
3de4643
add Context to some functions
ChingLongTin Nov 2, 2025
c3a1f5c
dedup Pattern with Block.Case
ChingLongTin Nov 2, 2025
d1170e9
rename mls{Block, Shape, Symbol} helpers
ChingLongTin Nov 3, 2025
36107df
amend! link to functions in Shape.mls
ChingLongTin Nov 3, 2025
ed393fc
flesh out {Block, Shape}.mls
ChingLongTin Nov 3, 2025
1c5fc1a
formatting
ChingLongTin Nov 3, 2025
38069b7
implement ruleMatch
ChingLongTin Nov 3, 2025
f1a209b
remove Label from Block.mls
ChingLongTin Nov 3, 2025
55f4fa1
rename helpers
ChingLongTin Nov 3, 2025
124232f
update Block.mls
ChingLongTin Nov 3, 2025
7c8f3d9
adapt NeilKleistGao's example code
ChingLongTin Nov 3, 2025
6997e89
rename helpers
ChingLongTin Nov 3, 2025
36abad1
refactor ruleMatch
ChingLongTin Nov 3, 2025
64960a8
fix ruleTup
ChingLongTin Nov 3, 2025
a264406
reduce supported cases to make mvp
ChingLongTin Nov 3, 2025
4ae8897
Update Syntax.mls
ChingLongTin Nov 1, 2025
88c3a5e
move detecting staged annotation to ClsLikeDefn
ChingLongTin Nov 4, 2025
17701b9
move importing to diff testing compiler flag
ChingLongTin Nov 4, 2025
5ccb64c
revert formatting changes
ChingLongTin Nov 4, 2025
980d89c
Update Printer.scala
ChingLongTin Nov 5, 2025
ce1e38c
Update Lowering.scala
ChingLongTin Nov 5, 2025
ec3e7b8
Merge branch 'hkmc2' into staged-syntax
ChingLongTin Nov 5, 2025
317c6f6
remove redundant :pt
ChingLongTin Nov 5, 2025
9023eec
fix syntax error
ChingLongTin Nov 5, 2025
9fc83dc
fix type hint for arms in Match
ChingLongTin Nov 5, 2025
7b702f3
add preliminary printCode function
yeungsinchun Nov 5, 2025
e4d7b22
move instrumentation to JSBackendDiffMaker
ChingLongTin Nov 6, 2025
6576f28
rename compiler flag to :staging
ChingLongTin Nov 6, 2025
4191464
Revert "remove redundant :pt"
ChingLongTin Nov 6, 2025
817e828
combine import statements to list
ChingLongTin Nov 6, 2025
e4f947d
Merge branch 'staged-syntax' into instrument
ChingLongTin Nov 6, 2025
33a3749
reword function
ChingLongTin Nov 6, 2025
b10e975
Revert "move instrumentation to JSBackendDiffMaker"
ChingLongTin Nov 6, 2025
b93b5eb
Merge branch 'staged-syntax' into instrument-simple
ChingLongTin Nov 6, 2025
791b5b4
prune implementation for mvp
ChingLongTin Nov 6, 2025
578dfd1
implement rudimentary instrumentation logic
ChingLongTin Nov 6, 2025
27bf507
implement printing for DynSelect
ChingLongTin Nov 6, 2025
9c975f6
only stage functions in staged modules
ChingLongTin Nov 6, 2025
ff6b121
update Syntax.mls
ChingLongTin Nov 6, 2025
068fd37
remove bugs in pretty printing
yeungsinchun Nov 7, 2025
f70f346
Merge branch 'pretty-print' into instrument-simple
yeungsinchun Nov 7, 2025
3f32b39
formatting
ChingLongTin Nov 8, 2025
d3bd300
add back Symbol class
ChingLongTin Nov 8, 2025
8ef91e9
reuse original function name
ChingLongTin Nov 8, 2025
3c7f58d
update test cases
ChingLongTin Nov 8, 2025
2ecda34
fix ruleVal
ChingLongTin Nov 8, 2025
9ebf26b
add some debug symbol names
ChingLongTin Nov 8, 2025
0198eb9
rename PathLike to ArgWrappable
ChingLongTin Nov 8, 2025
8fa331b
fix applyBlock impl
ChingLongTin Nov 9, 2025
e167b20
refactor transformFunDefn
ChingLongTin Nov 10, 2025
0e08e07
remove spread from Arg
ChingLongTin Nov 10, 2025
827f6af
clean up outdated comments and helpers
ChingLongTin Nov 10, 2025
57b45fd
implement ruleTup
ChingLongTin Nov 10, 2025
37eb7a1
formatting
ChingLongTin Nov 10, 2025
69f5997
implement ruleSel and ruleInst
ChingLongTin Nov 10, 2025
6831c61
remove outdated comment
ChingLongTin Nov 10, 2025
ab92537
clean up symName printing
ChingLongTin Nov 10, 2025
29c1109
formatting
ChingLongTin Nov 10, 2025
55fdf26
Add shape in diff testing
yeungsinchun Nov 11, 2025
1e0eb65
update note
ChingLongTin Nov 17, 2025
b93a91c
update PrintCode printout
ChingLongTin Nov 17, 2025
772c93a
update Shape constructors
ChingLongTin Nov 17, 2025
fbe45ea
add context
ChingLongTin Nov 17, 2025
873c8cc
remove outdated comments
ChingLongTin Nov 17, 2025
31809c7
correc comment
yeungsinchun Nov 20, 2025
91e5197
fix pretty print to print mlscript
yeungsinchun Nov 20, 2025
f1886ec
refactor
ChingLongTin Nov 20, 2025
d99eda9
follow JSBuilder pretty printing for DynSelect in Printer
ChingLongTin Nov 20, 2025
02303a3
remove Field from Case
ChingLongTin Nov 20, 2025
d6dc21e
change transformBlock signature
ChingLongTin Nov 20, 2025
cde7a68
implement more rules
ChingLongTin Nov 20, 2025
1f3ee7c
remove import Option from Shape.mls
ChingLongTin Nov 20, 2025
0499166
replace Multiple with ShapeSet
ChingLongTin Nov 20, 2025
fbb869c
misc fixes to Shape.mls
ChingLongTin Nov 20, 2025
adf5590
patch showLiteral for null and undefined
ChingLongTin Nov 20, 2025
ada9c3a
replace ruleVal
ChingLongTin Nov 21, 2025
9f6b1ab
clean up
ChingLongTin Nov 21, 2025
ba80ea4
add symbol to Class Shape for matching
ChingLongTin Nov 21, 2025
8efd61d
add spread field to Arg
ChingLongTin Nov 21, 2025
e19dbd6
update PrintCode.mls
ChingLongTin Nov 21, 2025
146a198
add ruleCls
ChingLongTin Nov 21, 2025
e1aedc7
formatting
ChingLongTin Nov 21, 2025
ed85e75
progress on rest of the rules
ChingLongTin Nov 21, 2025
53a0aa4
replace Block.Case with Pattern
ChingLongTin Nov 21, 2025
3a992ad
implement ShapeSet and ShapeMap
ChingLongTin Nov 21, 2025
5840db4
fix equality checks for Symbol
ChingLongTin Nov 22, 2025
bc2f624
implement Shape{Map, Set}
ChingLongTin Nov 22, 2025
e2454b4
fill out ShapeSet functionailty
ChingLongTin Nov 22, 2025
746cbd3
link ShapeSet symbols for instrumentation
ChingLongTin Nov 22, 2025
9915656
fix Shape, ShapeSet implementations
ChingLongTin Nov 22, 2025
4930252
remove TrivialResult
ChingLongTin Nov 22, 2025
b3c707f
replace Shape with ShapeSet during instrumentation
ChingLongTin Nov 23, 2025
e76c1fd
add message to assertions
ChingLongTin Nov 23, 2025
d792553
refactor match rules
ChingLongTin Nov 23, 2025
1020d38
add debug print Shape
ChingLongTin Nov 23, 2025
eece7ac
print more information for ClsLikeDefn
ChingLongTin Nov 23, 2025
df68b1d
combine Pattern with Case
ChingLongTin Nov 23, 2025
aa3b19a
fill out more match instrumentation
ChingLongTin Nov 23, 2025
4af5839
update comments
ChingLongTin Nov 23, 2025
2c67c8e
update PrintCode.mls
ChingLongTin Nov 23, 2025
c90118c
move optionNme inside stageCode scope
ChingLongTin Nov 23, 2025
f149026
Merge remote-tracking branch 'mlscript/hkmc2' into instrument
ChingLongTin Nov 23, 2025
aae0086
Revert "move optionNme inside stageCode scope"
ChingLongTin Nov 23, 2025
986ace7
use more meaningful names in Functions.mls
ChingLongTin Nov 23, 2025
f0456e1
refactor collectApply
ChingLongTin Nov 23, 2025
d510452
formatting
ChingLongTin Nov 23, 2025
0b2b7ea
update comments and debug info
ChingLongTin Nov 23, 2025
b6c86e1
remove redundant import
ChingLongTin Nov 24, 2025
869c519
match pretty printing syntax for DynSelect with formalization
ChingLongTin Nov 24, 2025
cff8896
fix mkClass
ChingLongTin Nov 24, 2025
0d95197
Merge branch 'hkmc2' into instrument
ChingLongTin Nov 24, 2025
8853371
formatting
ChingLongTin Nov 24, 2025
60c777c
Merge branch 'instrument' of https://github.com/ChingLongTin/mlscript…
ChingLongTin Nov 24, 2025
a343c36
fix syntax errors
ChingLongTin Nov 24, 2025
3c4faec
patch in instrumentation
ChingLongTin Nov 24, 2025
b7c3698
unreserve Option in Elaborator
ChingLongTin Nov 24, 2025
c149a11
remove argument names from class shape
ChingLongTin Nov 24, 2025
1f5c8d7
move functions
ChingLongTin Nov 24, 2025
a6b0162
add ClassSymbol
ChingLongTin Nov 24, 2025
c9f3c6a
formatting
ChingLongTin Nov 24, 2025
db7395d
clean up
ChingLongTin Nov 24, 2025
af3f436
Revert "move functions"
ChingLongTin Nov 24, 2025
89f414c
update diff output
yeungsinchun Nov 25, 2025
6db62ea
pass staged annotation in lowering
yeungsinchun Nov 26, 2025
c1f00e8
Revert "patch in instrumentation"
ChingLongTin Nov 26, 2025
143ce9b
rename functions
ChingLongTin Nov 24, 2025
fcbe8c9
add debug information to rules
ChingLongTin Nov 24, 2025
87b5457
move paramsOpt into ClassSymbol
ChingLongTin Nov 25, 2025
67a099c
implement pruning of bad arms from Match statement
ChingLongTin Nov 26, 2025
9f148af
add debug name to transformSymbol
ChingLongTin Nov 26, 2025
cd26ae1
remove code duplication from ruleBranch
ChingLongTin Nov 26, 2025
2b5b30a
fix typo
ChingLongTin Nov 26, 2025
8b459b3
Merge branch 'fix-pretty-print' into instrument
yeungsinchun Nov 26, 2025
5d63091
update pretty printing to print actual mlscript
yeungsinchun Nov 26, 2025
cc24cae
only pass the "staged" annotation for non-companion module
yeungsinchun Nov 26, 2025
2b1d157
Merge remote-tracking branch 'origin/instrument' into instrument
yeungsinchun Nov 26, 2025
bcafb98
reduce test cases
yeungsinchun Nov 26, 2025
b9eee38
fix class definition printing
yeungsinchun Nov 26, 2025
50f07ca
add match error on pretty printing
yeungsinchun Nov 26, 2025
678dbc9
fix test cases
yeungsinchun Nov 26, 2025
71a8918
some unimportant change
yeungsinchun Nov 26, 2025
7151735
some more unimportant change
yeungsinchun Nov 26, 2025
2548c78
Merge branch 'instrument-with-pretty-print' into instrument
yeungsinchun Nov 26, 2025
f582fa5
printed correctly now
yeungsinchun Nov 26, 2025
0a6087f
Revert "printed correctly now"
yeungsinchun Nov 26, 2025
cd7f7bc
Revert "Merge branch 'instrument-with-pretty-print' into instrument"
yeungsinchun Nov 26, 2025
34d0914
Revert "some more unimportant change"
yeungsinchun Nov 26, 2025
a3925e5
Revert "Merge remote-tracking branch 'origin/instrument' into instrum…
yeungsinchun Nov 26, 2025
79c90ee
Revert "update pretty printing to print actual mlscript"
yeungsinchun Nov 26, 2025
430d941
Merge branch 'hkmc2' into instrument
ChingLongTin Nov 26, 2025
ff58a1a
Reapply "Merge remote-tracking branch 'origin/instrument' into instru…
ChingLongTin Nov 27, 2025
50b6fd5
fix static impl
ChingLongTin Nov 27, 2025
087c960
add inf back to Tup
ChingLongTin Nov 26, 2025
302e310
fix showArg printing
ChingLongTin Nov 26, 2025
4d8e46c
add more Tup test cases
ChingLongTin Nov 26, 2025
f3ee1c6
formatting
ChingLongTin Nov 26, 2025
c703795
fix params type in FunDefn
ChingLongTin Nov 27, 2025
c124135
add Context to ruleEnd
ChingLongTin Nov 28, 2025
45b7b5e
uppdate Match rules
ChingLongTin Nov 28, 2025
408733a
mark pretty printing equality as fixme
ChingLongTin Nov 28, 2025
06312fb
Merge branch 'hkmc2' into instrument
ChingLongTin Dec 11, 2025
0e2fec8
progress: deprecate ShapeSet from StagedPath
ChingLongTin Dec 12, 2025
97ede40
progress: strip shape logic from rules
ChingLongTin Dec 12, 2025
d507d3f
remove inferring shape from Instrumentation
ChingLongTin Dec 12, 2025
ff7385d
progress: add StagedPath to ArgWrappable
ChingLongTin Dec 12, 2025
6db1ee7
progress: simplify impl
ChingLongTin Dec 12, 2025
977433a
progress: formatting
ChingLongTin Dec 12, 2025
b79613a
Merge branch 'hkmc2' into instrument
ChingLongTin Dec 12, 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
395 changes: 386 additions & 9 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Instrumentation.scala

Large diffs are not rendered by default.

12 changes: 9 additions & 3 deletions hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import semantics.Term.{Throw => _, *}
import semantics.Elaborator.{State, Ctx, ctx}

import syntax.{Literal, Tree}
import hkmc2.syntax.Fun
import hkmc2.syntax.{Fun, Keyword}


abstract class TailOp extends (Result => Block)
Expand Down Expand Up @@ -251,14 +251,20 @@ class Lowering()(using Config, TL, Raise, State, Ctx):
mod.classCompanion match
case S(comp) => comp.defn.getOrElse(wat("Module companion without definition", mod.companion))
case N =>
ClassDef.Plain(mod.owner, syntax.Cls, new ClassSymbol(Tree.DummyTypeDef(syntax.Cls), mod.sym.id),
val clsSymb = new ClassSymbol(Tree.DummyTypeDef(syntax.Cls), mod.sym.id)
val stagedAnnots = mod.annotations.collect {
case Annot.Modifier(Keyword.`staged`) => Annot.Modifier(Keyword.`staged`)
}
val newDefn = ClassDef.Plain(mod.owner, syntax.Cls, clsSymb,
mod.bsym,
Nil,
N,
ObjBody(Blk(Nil, UnitVal())),
S(mod.sym),
Nil,
stagedAnnots
)
clsSymb.defn = S(newDefn)
newDefn
case _ => _defn
reportAnnotations(defn, defn.extraAnnotations)
val bufferableAnnots = defn.annotations.flatMap:
Expand Down
3 changes: 2 additions & 1 deletion hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,9 @@ object Printer:
case Select(qual, name) =>
val docQual = mkDocument(qual)
doc"${docQual}.${name.name}"
case DynSelect(qual, fld, ai) =>
doc"${mkDocument(qual)}.(${mkDocument(fld)})"
case x: Value => mkDocument(x)
case _ => TODO(path)

def mkDocument(result: Result)(using Raise, Scope): Document = result match
case Call(fun, args) => doc"${mkDocument(fun)}(${args.map(mkDocument).mkDocument(", ")})"
Expand Down
3 changes: 2 additions & 1 deletion hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ object Elaborator:
val prettyPrintSymbol = TempSymbol(N, "prettyPrint")
val termSymbol = TempSymbol(N, "Term")
val blockSymbol = TempSymbol(N, "Block")
val shapeSymbol = TempSymbol(N, "Shape")
val shapeSetSymbol = TempSymbol(N, "shapeSet")
val optionSymbol = TempSymbol(N, "option")
val wasmSymbol = TempSymbol(N, "wasm")
val effectSigSymbol = ClassSymbol(DummyTypeDef(syntax.Cls), Ident("EffectSig"))
val nonLocalRetHandlerTrm =
Expand Down
176 changes: 176 additions & 0 deletions hkmc2/shared/src/test/mlscript-compile/Block.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import "./Predef.mls"
import "./Option.mls"
import "./StrOps.mls"

open Predef
open StrOps
open Option

module Block with...

type Opt[A] = Option[A]

// dependancies referenced in Block classes, referencing implementation in Term.mls

type Literal = null | undefined | Str | Int | Num | Bool

type ParamList = Array[Symbol]

class Symbol(val name: Str)
type Ident = Symbol
// this is so that we're able to retrieve information about the class from the symbol
class ClassSymbol(val name: Str, val paramsOpt: Opt[ParamList]) extends Symbol(name)

class Arg(val spread: Opt[Bool], val value: Path)

class Case with
constructor
Lit(val lit: Literal)
Cls(val cls: Symbol, val path: Path)
Tup(val len: Int, val inf: Bool)

class Result with
constructor
Call(val _fun: Path, val args: Array[Arg])
Instantiate(val cls: Path, val args: Array[Arg]) // assume immutable
Tuple(val elems: Array[Arg]) // assume immutable

class Path extends Result with
constructor
Select(val qual: Path, val name: Ident)
DynSelect(val qual: Path, val fld: Path, val arrayIdx: Bool) // is arrayIdx used?
ValueRef(val l: Symbol)
ValueLit(val lit: Literal)

class Defn with
constructor
ValDefn(val sym: Symbol, val rhs: Path)
ClsLikeDefn(val sym: ClassSymbol, val companion: Opt[ClsLikeBody]) // companion unused
FunDefn(val sym: Symbol, val params: Array[ParamList], val body: Block, val stage: Bool)

class ClsLikeBody(val isym: Symbol, val methods: Array[FunDefn], val publicFields: Array[[Symbol, Symbol]]) // unused

class Block with
constructor
Match(val scrut: Path, val arms: Array[[Case, Block]], val dflt: Opt[Block], val rest: Block)
Return(val res: Result, val implct: Bool)
Assign(val lhs: Symbol, val rhs: Result, val rest: Block)
Define(val defn: Defn, val rest: Block)
End()

fun concat(b1: Block, b2: Block) = if b1 is
Match(scrut, arms, dflt, rest) then Match(scrut, arms, dflt, concat(rest, b2))
Return(res, implct) then b2 // discard return?
Assign(lhs, rhs, rest) then Assign(lhs, rhs, concat(rest, b2))
Define(defn, rest) then Define(defn, concat(rest, b2))
End() then b2

fun showBool(b: Bool) = if b then "true" else "false"

fun showLiteral(l: Literal) =
if l is
undefined then "undefined"
null then "null"
String then "\"" + l.toString() + "\""
else l.toString()

fun showSymbol(s: Symbol) =
// console.log("printing " + s)
if s is
ClassSymbol(name, args) then
"ClassSymbol(" + "\"" + name + "\"" +
if args
is Some(args) then ":[" + args.map(showSymbol).join(", ") + "]"
is None then ""
+ ")"
_ then "Symbol(" + "\"" + s.name + "\"" + ")"

fun showIdent(i: Ident) = showSymbol(i)

fun showPath(p: Path): Str =
if p is
Select(qual, name) then
"Select(" + showPath(qual) + ", " + showIdent(name) + ")"
DynSelect(qual, fld, arrayIdx) then
"DynSelect(" + showPath(qual) + ", " + showPath(fld) + ", " + showBool(arrayIdx) + ")"
ValueRef(l) then
"Ref(" + showSymbol(l) + ")"
ValueLit(lit) then
"Lit(" + showLiteral(lit) + ")"

fun showArg(arg: Arg) =
if arg.spread is
Some(true) then "..."
Some(false) then ".."
else ""
+ showPath(arg.value)

fun showArgs(args: Array[Arg]) =
"[" + args.map(showArg).join(", ") + "]"

// Case (match arm patterns)
fun showCase(c: Case): Str =
if c is
Lit(lit) then "Lit(" + showLiteral(lit) + ")"
Cls(cls, path) then "Cls(" + showSymbol(cls) + ", " + showPath(path) + ")"
Tup(len, inf) then "Tup(" + len + ", " + inf + ")"

fun showResult(r: Result): Str =
if r is
Path then showPath(r)
Call(f, args) then "Call(" + showPath(f) + ", " + showArgs(args) + ")"
Instantiate(cls, args) then "Instantiate(" + showPath(cls) + ", " + showArgs(args) + ")"
Tuple(elems) then "Tuple(" + showArgs(elems) + ")"

fun showParamList(ps: ParamList) =
"[" + ps.map(s => showSymbol(s)).join(", ") + "]"

fun showDefn(d: Defn): Str =
if d is
ValDefn(sym, rhs) then
"ValDefn(" + showSymbol(sym) + ", " + showPath(rhs) + ")"
FunDefn(sym, params, body, stage) then
"FunDefn(" + showSymbol(sym) + ", " +
"(" + params.map(showParamList) + "), " +
showBlock(body) + ", "
+ stage + ")"
ClsLikeDefn(sym, companion) then
// TODO: print rest of the arguments
"ClsLikeDefn(" + showSymbol(sym) + ", " + "TODO" + ")"

fun showOptBlock(ob: Opt[Block]) =
if ob is Some(b) then showBlock(b) else "None"

fun showArm(pair: Case -> Block) =
if pair is [cse, body] then showCase(cse) + " -> " + showBlock(body) else "<bad-arm>"

fun showBlock(b: Block): Str =
if b is
Match(scrut, arms, dflt, rest) then
"Match(" +
showPath(scrut) + ", " +
"[" + arms.map(showArm).join(", ") + "], " +
showOptBlock(dflt) + ", " +
showBlock(rest) + ")"
Return(res, implct) then
"Return(" + showResult(res) + ", " + showBool(implct) + ")"
Assign(lhs, rhs, rest) then
"Assign(" + showSymbol(lhs) + ", " + showResult(rhs) + ", " + showBlock(rest) + ")"
Define(defn, rest) then
"Define(" + showDefn(defn) + ", " + showBlock(rest) + ")"
End() then "End"

fun show(x) =
if x is
Symbol then showSymbol(x)
Path then showPath(x)
Result then showResult(x)
Case then showCase(x)
Defn then showDefn(x)
Block then showBlock(x)
else
"<unknown>"

fun printCode(x) = print(show(x))

fun compile(p: Block) = ???
122 changes: 122 additions & 0 deletions hkmc2/shared/src/test/mlscript-compile/Shape.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import "./Block.mls"
import "./Option.mls"

open Block { Literal, Symbol, ClassSymbol, showSymbol }
open Option

type Shape = Shape.Shape

fun isPrimitiveType(sym: Symbol) =
if sym.name is
"Str" then true
"Int" then true
"Num" then true
"Bool" then true
else false

fun isPrimitiveTypeOf(sym: Symbol, l: Literal) =
if [sym.name, l] is
["Str", l] and l is Str then true
["Int", i] and i is Int then true
["Num", n] and n is Num then true
["Bool", b] and b is Bool then true
else false

module Shape with...

class Shape with
constructor
Dyn()
Lit(val l: Literal)
Arr(val shapes: Array[Shape], val inf: Bool)
Class(val sym: ClassSymbol, val params: Array[Shape])

// FIXME: hack to check equality of classes if they have the same paramters
fun equals(a: Shape, b: Shape) = show(a) == show(b)

fun show(s: Shape) =
if s is
Dyn then "Dyn"
Lit(lit) then "Lit(" + Block.showLiteral(lit) + ")"
Arr(shapes, inf) then "Arr([" + shapes.map(show).join(", ") + "], " + inf + ")"
Class(sym, params) then "Class(" + showSymbol(sym) + ", [" + params.map(show).join(", ") + "])"

fun zipMrg[A](a: Array[A], b: Array[A]): Array[A] =
a.map((a, i, _) => mrg2(a, b.at(i)))

fun mrg2(s1: Shape, s2: Shape) =
if equals(s1, s2) then s1
else if [s1, s2] is
[Lit(l), Class(sym, params)]
and isPrimitiveTypeOf(sym, l)
then Class(sym, params)
[Class(sym1, ps), Class(sym2, s2)]
and sym1.name == sym2.name
then Class(sym1, ps.map(p => [p.0, zipMrg(p.1, s2)]))
[Arr(s1, false), Arr(s2, false)]
and s1.length == s2.length
then Arr(zipMrg(s1, s2), false)
else Dyn()

fun mrg(s1: Array[Shape]) =
s1.reduceRight((acc, s, _, _) => mrg2(s, acc))

fun sel(s1: Shape, s2: Shape): Array[Shape] =
if [s1, s2] is
[Class(sym, params), Lit(n)] and n is Str
and sym.args is Some(args)
and args.find(_ == n)
== () then []
is i then [params.(i)]
[Dyn, Lit(n)] and n is Str
then [Dyn()]
[Arr(shapes, false), Lit(n)] and n is Int
then [shapes.(n)]
[Arr(shapes, false), Dyn] then
shapes
[Arr(shapes, true), _] then [Dyn()] // TODO
[Dyn, Lit(n)] and n is Int
then [Dyn()]
[Dyn, Dyn]
then [Dyn()]
else [] // TODO: return no possibility instead of err?

fun static(s: Shape) =
if s is
Dyn then false
Lit(l) then not (l is Str and isPrimitiveType(l)) // redundant bracket?
Class(_, params) then params.every(static)
Arr(shapes, false) then shapes.every(static)
Arr(shapes, true) then false // TODO

open Block { Case }

fun silh(p: Case): Shape = if p is
Block.Lit(l) then Lit(l)
Block.Cls(sym, path) then
val size = if sym.args is Some(i) then i else 0
Class(sym, Array(size).fill(Dyn))
Block.Tup(n, inf) then Arr(Array(n).fill(Dyn), inf)

// TODO: use Option instead, since all of them return at most one shape
fun filter(s: Shape, p: Case): Array[Shape] =
if [s, p] is
[Lit(l1), Block.Lit(l2)] and l1 == l2 then [s]
[Lit(l), Block.Cls(c, _)] and isPrimitiveTypeOf(c, l) then [s]
[Arr(ls, false), Block.Tup(n, false)] and ls.length == n then [s]
[Arr(ls, true), _] then [s] // TODO
[_, Block.Tup(ls, true)] then [s] // TODO
[Class(c1, _), Block.Cls(c2, _)] and c1.name == c2.name then [s]
[Dyn, _] then [silh(p)]
else []

fun rest(s: Shape, p: Case): Array[Shape] =
if [s, p] is
[Lit(l1), Block.Lit(l2)] and l1 == l2 then []
[Lit(l), Block.Cls(c, _)] and isPrimitiveTypeOf(c, l) then []
[Arr(ls, false), Block.Tup(n, false)] and ls.length == n then []
[Arr(ls, true), _] then [s] // TODO
[_, Block.Tup(ls, true)] then [s] // TODO
[Class(c1, _), Block.Cls(c2, _)] and c1.name == c2.name then []
[Dyn, _] then [s]
else [s]
19 changes: 19 additions & 0 deletions hkmc2/shared/src/test/mlscript-compile/ShapeMap.mls
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "./Option.mls"
import "./ShapeSet.mls"

open Option { Some, None }
open ShapeSet

type ShapeMap = ShapeMap.ShapeMap

module ShapeMap with...

fun hash(s: ShapeSet) = s.keys().join(", ")

class ShapeMap(val underlying: Map) with
fun add(s: ShapeSet, code) = underlying.set(hash(s), code)

fun get(s: ShapeSet) =
if underlying.get(hash(s))
== () then None
is value then Some of value
Loading
Loading