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

define tuples up to 32 #1078

Merged
merged 4 commits into from
Dec 8, 2023
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
72 changes: 67 additions & 5 deletions core/src/main/resources/bosatsu/predef.bosatsu
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,38 @@ export (
List(),
String,
Test(),
TupleCons(),
Tuple1(),
Tuple2(),
Tuple3(),
Tuple4(),
Tuple5(),
Tuple6(),
Tuple7(),
Tuple8(),
Tuple9(),
Tuple10(),
Tuple11(),
Tuple12(),
Tuple13(),
Tuple14(),
Tuple15(),
Tuple16(),
Tuple17(),
Tuple18(),
Tuple19(),
Tuple20(),
Tuple21(),
Tuple22(),
Tuple23(),
Tuple24(),
Tuple25(),
Tuple26(),
Tuple27(),
Tuple28(),
Tuple29(),
Tuple30(),
Tuple31(),
Tuple32(),
Order(),
Unit(),
Dict,
Expand Down Expand Up @@ -49,7 +80,38 @@ export (
)

struct Unit
struct TupleCons(first, second)
struct Tuple1[a: +*](item1: a)
struct Tuple2[a: +*, b: +*](item1: a, item2: b)
struct Tuple3[a: +*, b: +*, c: +*](item1: a, item2: b, item3: c)
struct Tuple4[a: +*, b: +*, c: +*, d: +*](item1: a, item2: b, item3: c, item4: d)
struct Tuple5[a: +*, b: +*, c: +*, d: +*, e: +*](item1: a, item2: b, item3: c, item4: d, item5: e)
struct Tuple6[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f)
struct Tuple7[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g)
struct Tuple8[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h)
struct Tuple9[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i)
struct Tuple10[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j)
struct Tuple11[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k)
struct Tuple12[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l)
struct Tuple13[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m)
struct Tuple14[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n)
struct Tuple15[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o)
struct Tuple16[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p)
struct Tuple17[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q)
struct Tuple18[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r)
struct Tuple19[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s)
struct Tuple20[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t)
struct Tuple21[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u)
struct Tuple22[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v)
struct Tuple23[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w)
struct Tuple24[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x)
struct Tuple25[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y)
struct Tuple26[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z)
struct Tuple27[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0)
struct Tuple28[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*, b0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0, item28: b0)
struct Tuple29[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*, b0: +*, c0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0, item28: b0, item29: c0)
struct Tuple30[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*, b0: +*, c0: +*, d0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0, item28: b0, item29: c0, item30: d0)
struct Tuple31[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*, b0: +*, c0: +*, d0: +*, e0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0, item28: b0, item29: c0, item30: d0, item31: e0)
struct Tuple32[a: +*, b: +*, c: +*, d: +*, e: +*, f: +*, g: +*, h: +*, i: +*, j: +*, k: +*, l: +*, m: +*, n: +*, o: +*, p: +*, q: +*, r: +*, s: +*, t: +*, u: +*, v: +*, w: +*, x: +*, y: +*, z: +*, a0: +*, b0: +*, c0: +*, d0: +*, e0: +*, f0: +*](item1: a, item2: b, item3: c, item4: d, item5: e, item6: f, item7: g, item8: h, item9: i, item10: j, item11: k, item12: l, item13: m, item14: n, item15: o, item16: p, item17: q, item18: r, item19: s, item20: t, item21: u, item22: v, item23: w, item24: x, item25: y, item26: z, item27: a0, item28: b0, item29: c0, item30: d0, item31: e0, item32: f0)

enum Bool:
False, True
Expand Down Expand Up @@ -138,13 +200,13 @@ external def mod_Int(a: Int, mod: Int) -> Int
external def int_loop(intValue: Int, state: a, fn: (Int, a) -> (Int, a)) -> a

def range(exclusiveUpper: Int) -> List[Int]:
int_loop(exclusiveUpper, [], \i, tail ->
int_loop(exclusiveUpper, [], (i, tail) ->
inext = i.sub(1)
(inext, [inext, *tail]))

def range_fold(inclusiveLower: Int, exclusiveUpper: Int, init: a, fn: (a, Int) -> a) -> a:
diff = exclusiveUpper.sub(inclusiveLower)
int_loop(diff, init, \diff0, a ->
int_loop(diff, init, (diff0, a) ->
idx = exclusiveUpper.sub(diff0)
a1 = fn(a, idx)
(diff0.sub(1), a1))
Expand Down Expand Up @@ -337,7 +399,7 @@ struct Dict[k, v: +*](order: forall a. Order[(k, a)], tree: Tree[(k, v)])

def empty_Dict(comp: Order[k]) -> forall v. Dict[k, v]:
Order(fn) = comp
pair_ord = Order(\(k1, _), (k2, _) -> fn(k1, k2))
pair_ord = Order(((k1, _), (k2, _)) -> fn(k1, k2))
Dict(pair_ord, Empty)

def add_key(dict: Dict[k, v], key: k, value: v) -> Dict[k, v]:
Expand Down
6 changes: 5 additions & 1 deletion core/src/main/scala/org/bykn/bosatsu/PackageMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,11 @@ object PackageMap {
case Some(inf) => inf
}
case Validated.Invalid(errs) =>
sys.error(s"expected no errors, found: $errs")
val map = Map(PackageName.PredefName -> (LocationMap(Predef.predefString), "<predef>"))
errs.iterator.foreach { err =>
println(err.message(map, LocationMap.Colorize.None))
}
sys.error("expected no errors")
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/org/bykn/bosatsu/Predef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ object PredefImpl {
def gcd_Int(a: Value, b: Value): Value =
VInt(gcdBigInteger(i(a), i(b)))

//def intLoop(intValue: Int, state: a, fn: Int -> a -> TupleCons[Int, TupleCons[a, Unit]]) -> a
//def intLoop(intValue: Int, state: a, fn: Int -> a -> Tuple2[Int, a]) -> a
final def intLoop(intValue: Value, state: Value, fn: Value): Value = {
val fnT = fn.asFn

Expand All @@ -125,7 +125,7 @@ object PredefImpl {
if (bi.compareTo(BigInteger.ZERO) <= 0) state
else {
fnT(NonEmptyList(biValue, state :: Nil)) match {
case ConsValue(nextI, ConsValue(ConsValue(nextA, _), _)) =>
case ConsValue(nextI, ConsValue(nextA, _)) =>
val n = i(nextI)
if (n.compareTo(bi) >= 0) {
// we are done in this case
Expand Down
104 changes: 73 additions & 31 deletions core/src/main/scala/org/bykn/bosatsu/SourceConverter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,71 @@ final class SourceConverter(
}
}


private val unitName = Identifier.Constructor("Unit")
// this is lazy so it isn't initialized before Type
private lazy val tup: Array[Declaration => Expr[Declaration]] =
(Iterator.single(
{ (tc: Declaration) =>
Expr.Global(PackageName.PredefName, unitName, tc)
}
) ++ (1 to Type.FnType.MaxSize)
.iterator
.map { idx =>
val tup = Type.Tuple.Arity(idx)
val defined = tup.tpe.toDefined
val pn = defined.packageName
val cn = defined.name.ident

{ (tc: Declaration) => Expr.Global(pn, cn, tc) }
}).toArray

private def makeTuple(tc: Declaration, args: List[Declaration])(conv: Declaration => Result[Expr[Declaration]]): Result[Expr[Declaration]] =
args.traverse(conv)
.flatMap { exps =>
val size = exps.length
if (size <= Type.FnType.MaxSize) {
val fn = tup(size)(tc)
val res = Expr.buildApp(fn, exps, tc)
success(res)
}
else {
SourceConverter.failure(
SourceConverter.TooManyConstructorArgs(
Type.Tuple.Arity(32).tpe.toDefined.name.ident,
size, 32, tc.region)
)
}
}

private val unitPat =
success(Pattern.PositionalStruct(
(PackageName.PredefName, unitName),
Nil))

def makeTuplePattern[A](args: List[Pattern[(PackageName, Constructor), A]], region: Region): Result[Pattern[(PackageName, Constructor), A]] =
args match {
case Nil => unitPat
case nonEmpty =>
val size = nonEmpty.size
val tupleCons = Type.Tuple.Arity(size)
val defined = tupleCons.tpe.toDefined
val pat = Pattern.PositionalStruct(
(defined.packageName, defined.name.ident),
nonEmpty)
if (size <= Type.FnType.MaxSize) {
success(pat)
}
else {
SourceConverter.partial(
SourceConverter.TooManyConstructorArgs(
Type.Tuple.Arity(32).tpe.toDefined.name.ident,
size, 32, region),
pat
)
}
}

private def fromDecl(decl: Declaration, bound: Set[Bindable], topBound: Set[Bindable]): Result[Expr[Declaration]] = {
implicit val parAp = SourceConverter.parallelIor
def loop(decl: Declaration) = fromDecl(decl, bound, topBound)
Expand Down Expand Up @@ -292,21 +357,7 @@ final class SourceConverter(
val branches = NonEmptyList((p, True), (Pattern.WildCard, False) :: Nil)
Expr.Match(a, branches, m)
}
case tc@TupleCons(its) =>
val tup0: Expr[Declaration] = Expr.Global(PackageName.PredefName, Identifier.Constructor("Unit"), tc)
val tup2: Expr[Declaration] = Expr.Global(PackageName.PredefName, Identifier.Constructor("TupleCons"), tc)
def tup(args: List[Declaration]): Result[Expr[Declaration]] =
args match {
case Nil => success(tup0)
case h :: tail =>
val tailExp = tup(tail)
val headExp = loop(h)
(headExp, tailExp).mapN { (h, t) =>
Expr.buildApp(tup2, h :: t :: Nil, tc)
}
}

tup(its)
case tc@TupleCons(its) => makeTuple(tc, its)(loop)
case s@StringDecl(parts) =>
// a single string item should be converted
// to that thing,
Expand Down Expand Up @@ -773,21 +824,7 @@ final class SourceConverter(
pat.traversePattern[Result, (PackageName, Constructor), rankn.Type]({
case (Pattern.StructKind.Tuple, args) =>
// this is a tuple pattern
def loop[A](args: List[Pattern[(PackageName, Constructor), A]]): Pattern[(PackageName, Constructor), A] =
args match {
case Nil =>
// ()
Pattern.PositionalStruct(
(PackageName.PredefName, Constructor("Unit")),
Nil)
case h :: tail =>
val tailP = loop(tail)
Pattern.PositionalStruct(
(PackageName.PredefName, Constructor("TupleCons")),
h :: tailP :: Nil)
}

args.map(loop(_))
args.flatMap(makeTuplePattern(_, region))
case (Pattern.StructKind.Named(nm, Pattern.StructKind.Style.TupleLike), rargs) =>
rargs.flatMap { args =>
val pc@(p, c) = nameToCons(nm)
Expand Down Expand Up @@ -1542,6 +1579,11 @@ object SourceConverter {

final case class TooManyConstructorArgs(name: Constructor, argCount: Int, max: Int, region: Region) extends Error {
def message =
Doc.text(s"invalid argument count in constructor for ${name.asString} found $argCount maximum allowed $max").render(80)
if (name.asString == "Tuple32") {
Doc.text(s"invalid tuple size. Found $argCount, but maximum allowed ${Type.FnType.MaxSize}").render(80)
}
else {
Doc.text(s"invalid argument count in constructor for ${name.asString} found $argCount maximum allowed $max").render(80)
}
}
}
24 changes: 2 additions & 22 deletions core/src/main/scala/org/bykn/bosatsu/Value.scala
Original file line number Diff line number Diff line change
Expand Up @@ -137,37 +137,17 @@ object Value {
val False: SumValue = SumValue(0, UnitValue)
val True: SumValue = SumValue(1, UnitValue)

object TupleCons {
def unapply(v: Value): Option[(Value, Value)] =
v match {
case ConsValue(a, ConsValue(b, UnitValue)) => Some((a, b))
case _ => None
}

def apply(a: Value, b: Value): ProductValue =
ConsValue(a, ConsValue(b, UnitValue))
}

object Tuple {
/**
* Tuples are encoded as:
* (1, 2, 3) => TupleCons(1, TupleCons(2, TupleCons(3, ())))
* since a Tuple(a, b) is encoded as
* ConsValue(a, ConsValue(b, UnitValue))
* this gives double wrapping
*/
def unapply(v: Value): Option[List[Value]] =
v match {
case TupleCons(a, b) =>
unapply(b).map(a :: _)
case UnitValue => Some(Nil)
case p: ProductValue => Some(p.toList)
case _ => None
}

def fromList(vs: List[Value]): ProductValue =
vs match {
case Nil => UnitValue
case h :: tail => TupleCons(h, fromList(tail))
case h :: tail => ConsValue(h, fromList(tail))
}

def apply(vs: Value*): ProductValue =
Expand Down
Loading
Loading