hydra-scala 0.17.5 → 0.17.6
raw patch · 8 files changed
+212/−44 lines, 8 filesdep ~hydra-jvmdep ~hydra-kernelPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hydra-jvm, hydra-kernel
API changes (from Hackage documentation)
Files
- CHANGELOG.md +162/−0
- hydra-scala.cabal +4/−4
- src/main/haskell/Hydra/Dsl/Scala/Syntax.hs +1/−0
- src/main/haskell/Hydra/Scala/Coder.hs +14/−13
- src/main/haskell/Hydra/Scala/Language.hs +1/−0
- src/main/haskell/Hydra/Scala/Serde.hs +27/−26
- src/main/haskell/Hydra/Scala/Syntax.hs +1/−0
- src/main/haskell/Hydra/Scala/Utils.hs +2/−1
CHANGELOG.md view
@@ -15,6 +15,168 @@ --- +## [0.17.6] - 2026-08-30++Point release on the 0.17.x line, and the last backward-incompatible batch before the 1.0 surface+freeze. Five kernel-surface changes land together as the "0.17 breaking batch":+`null` becomes `isEmpty`, `read*`/`show*` become `parse*`/`print*`, `TypeScheme.constraints` and+`TypeVariableConstraints.classes` change shape, and the constructor primitives are finalized.+Alongside them, a genuine soundness gap in type inference is fixed — class constraints now propagate+through function-domain positions — and the cold-seed path is rebuilt on the Java host so that+breaking core-type changes are no longer structurally impossible to bootstrap.++**Backward-incompatible.** All five surface changes below alter the published kernel. Code written+against 0.17.5 must be updated:++- **[#682]** `hydra.lib.{lists,sets,maps,strings}.null` -> `.isEmpty`.+- **[#691]** the `read*`/`show*` family -> `parse*`/`print*`.+- **[#683]** `TypeScheme.constraints`: `optional<map>` -> plain `map`.+- **[#685]** `TypeVariableConstraints.classes`: `list` -> `set`.+- **[#687]** constructor primitives finalized: `lists.pure` is removed; `optionals.given`,+ `eithers.left`/`right` and `pairs.pair` are added.++[#682]: https://github.com/CategoricalData/hydra/issues/682+[#683]: https://github.com/CategoricalData/hydra/issues/683+[#685]: https://github.com/CategoricalData/hydra/issues/685+[#687]: https://github.com/CategoricalData/hydra/issues/687+[#691]: https://github.com/CategoricalData/hydra/issues/691++### Highlights++- **Class constraints propagate through contravariant positions**+ ([#702](https://github.com/CategoricalData/hydra/issues/702)): inference silently dropped a class+ constraint when the constrained type variable was bound through the **domain** (input) position of a+ higher-order function argument, while transferring it correctly in output positions — a real soundness+ gap in the type checker. It had been papered over twice by freezing `encodeMap`/`encodeSet` to+ monomorphic `Int`. Both freezes and the [#554](https://github.com/CategoricalData/hydra/issues/554)+ `toPrimitive` stopgap are now removed, the definitions re-polymorphized, and a domain-position+ regression test added. A `sets.filter` overlay lands across Java, Python, Scala, TypeScript and the+ Lisp dialects as its first consumer.+- **Cold-seed rebuilt on the Java host**+ ([#703](https://github.com/CategoricalData/hydra/issues/703)): CI's cold-seed steps compiled HEAD's+ kernel `Types` source against the *published* Hackage `hydra-kernel`, which is sound only for additive+ changes and structurally impossible for any breaking core-type-shape change — the root of a recurring+ red-CI class (#500, #608, #617, #417, #683). The Haskell cold-seeder (`ColdSeedMain`, `typesmods/`,+ Check-2) is deleted and replaced by a data-driven Java-host schema-walking seed+ (`seed-dist-haskell.sh`), which decodes `dist/json` and emits Haskell text without ever linking+ HEAD types against a published kernel.+- **`hydra.paths` completed** ([#716](https://github.com/CategoricalData/hydra/issues/716)):+ the step unions are realigned with the `hydra.core` term and type grammars — missing variants+ added (`annotatedAnnotation`, `eitherLeft`/`eitherRight`, `effect`), undirected steps given a+ direction, and variants named after retired constructors renamed. `hydra.print.paths` is rewritten+ as serialization-only (printers, parsers and a round-trip law), and the graph view moves to a new+ `hydra.shredding` module (`shredGraph`/`shredTerm`/`shredSchema`), which the Graphviz coder now+ consumes.+- **`hydra.lib.ordering` is genuinely structural on every host**+ ([#718](https://github.com/CategoricalData/hydra/issues/718)): the Java, Python and Scala overlay+ implementations fell back to comparing *printed strings* for non-literal and mixed-variant terms,+ contradicting the normative `ordering-and-equality.md` (records field-by-field in declaration+ order, unions by declared-variant order then payload, wrappers by wrapped value, decimals by+ numeric value then scale — with no print-based fallback anywhere). All three are now structural;+ Java delegates to the generated `compareTo`.+- **Bash driver-layer audit** ([#714](https://github.com/CategoricalData/hydra/issues/714)):+ a prerequisite to the remaining #416 promotion. Six dead build scripts superseded by+ `transform-json-to-target.sh` are deleted, and the #608 oil-and-water and #540 header-idempotency+ regression harnesses are wired into `test-regressions.sh`.++- **Backward-compatibility and deprecation policy**+ ([#676](https://github.com/CategoricalData/hydra/issues/676)): adds the normative spec chapter defining+ what "compatible" means after 1.0 — the additivity calculus, the deprecation/rename mechanism, and+ enforcement. `LifecycleInfo.deprecatedSince` moves from defined-but-unused to populated on **32**+ kernel primitives slated for 0.18 deprecation, via a new `deprecatedSince` DSL helper.+- **Effect-sequencing contract specified and tested**+ ([#675](https://github.com/CategoricalData/hydra/issues/675)): `hydra.lib.effects` carries a sequencing+ contract — effects composed in a specified order, exactly once each, with `bind`'s continuation deferred+ until the prior effect has run. On the lazy Haskell host this falls out of the evaluation model; on the+ eight eager hosts it depended entirely on each hand-written interpreter. The obligations are now written+ into `effects.md` and backed by ordering-observation tests for `bind`/`foldList`/`mapList`/`mapOptional`.+- **Non-GC memory-discipline investigation**+ ([#678](https://github.com/CategoricalData/hydra/issues/678)): Hydra's data model says nothing about+ allocation, freeing, or ownership, which is what gates Swift, Rust, C++ and C as runtime hosts. This+ investigation delivers per-language verdicts plus leak-free proof-of-concept implementations — Rust+ (`Box` structural ownership), C++ (`unique_ptr` + arena) and C (arena), all ASan/LSan-clean on+ construct-and-drop of a recursive `Term` — and an airtight analysis of Swift's class-forcing requirement.+- **Build system promotion continues** ([#416](https://github.com/CategoricalData/hydra/issues/416)):+ adds `hydra.build.Registry`, which models per-language build identity as data (name / coder package /+ family) with per-script scope lists. `syncMatrix` and `langExpansion` are rewired onto it, and the+ hardcoded language lists in the test and bench scripts are retired in favour of a generated+ `languages.json`. Later in the cycle: `publishsets.reverseDepClosure` and+ `publishsets.requiresCoders` promote reverse-dependency propagation and per-package coder-loading+ into data, an `expected-libraries.json` artifact lets the Common Lisp and Emacs Lisp harnesses+ fail fast on a missing `hydra.lib`, and a host-independent `apply-assembly-plan.sh` executor+ (with a conformance test) takes over the Java `assemble-distribution` Step 0.+- **Serialization specification chapter**+ ([#674](https://github.com/CategoricalData/hydra/issues/674)): documents serializability, the+ encode/decode contract, and the round-trip law; `isSerializable` now forbids `void`+ ([#690](https://github.com/CategoricalData/hydra/issues/690)), and `hydra.lib.functions.absurd` is added+ as the void eliminator ([#684](https://github.com/CategoricalData/hydra/issues/684)).++### Bug fixes++- **Hoisting silently produced terms with free variables**+ ([#717](https://github.com/CategoricalData/hydra/issues/717)):+ `augmentBindingsWithNewFreeVars` returned a binding *unchanged* when a captured variable had no+ type in the context, yielding a top-level binding with free variables — a term valid before+ hoisting and invalid after, produced with no error. It is now total and fails loudly, per the+ kernel's fail-immediately rule.+- **TypeScript `div`/`mod` used truncating semantics**+ ([#677](https://github.com/CategoricalData/hydra/issues/677)): corrected to floor/Knuth division via+ shared bigint helpers, with an `Optional` codomain; the dead `maybeDiv`/`maybeMod` are deleted and an+ emitted-path test added.+- **Overlay lag behind the `null` -> `isEmpty` rename**+ ([#682](https://github.com/CategoricalData/hydra/issues/682)): the Java, Python, Scala, TypeScript and+ Lisp overlays each kept a stale spelling (`isEmpty_`, a half-renamed Python `null` impl, and Lisp+ camelCase where the coder emits snake_case), breaking generation until reconciled.+- **`check-haskell-def-completeness` could not resolve qualified assembly references**+ ([#683](https://github.com/CategoricalData/hydra/issues/683)), surfaced once the #703 cold-clone path+ began reaching the check.+- **Void-typed definitions leaked into DSL-ref generation**+ ([#684](https://github.com/CategoricalData/hydra/issues/684)): `absurd` and friends are now excluded+ across all hosts.+- **Scheme bootstrap loader gaps** ([#641](https://github.com/CategoricalData/hydra/issues/641)):+ missing `functions.scm`/`ordering.scm` in the native-lib load list, missing defaults in the def-module+ load list, and a guile-only import allowlist.+- **Bootstrap diff detail was swallowed** ([#671](https://github.com/CategoricalData/hydra/issues/671)):+ now persisted to `<run>/<path>.diff`, with `compare_output`'s return value no longer discarded.+ Separately, `compare_output` mis-derived the `src/main` vs `src/test` root per file+ ([#706](https://github.com/CategoricalData/hydra/issues/706)).+- **Nested duplicate output path** ([#664](https://github.com/CategoricalData/hydra/issues/664)) from+ `hydra-kernel` being hardcoded into `defaultOutput`.+- **Bootstrap codegen exceptions hid their stack traces**+ ([#707](https://github.com/CategoricalData/hydra/issues/707)) in `bootstrap.ts`.++### Release tooling++- `bin/check-release-env.sh` ([#704](https://github.com/CategoricalData/hydra/issues/704)) adds a+ publish-time toolchain preflight, after JDK- and twine-version problems cost real time at 0.17.5.+- The TypeScript head's node floor is lowered to `^18.0.0 || >=20.0.0`, the true vitest constraint+ ([#708](https://github.com/CategoricalData/hydra/issues/708)).+- Hydra does not create GitHub Releases; the detached `.asc` signature stays in `release-artifacts/`+ until [#441](https://github.com/CategoricalData/hydra/issues/441)+ ([#508](https://github.com/CategoricalData/hydra/issues/508)).++### Known issues++- The `hostOverrides` shim is pinned to `{java: local, python: local}` for the duration of the breaking+ batch, since the new kernel surface is by definition absent from published 0.17.5. It must be retired+ once 0.17.6 is visible in Maven Central and PyPI+ ([#508](https://github.com/CategoricalData/hydra/issues/508)).+- **`hydra-ext` does not ship to Maven Central for Java**, as in 0.17.4 and 0.17.5: the Java coder's+ visitor-pattern inner interface still collides with an enclosing type named `Visitor`+ ([#643](https://github.com/CategoricalData/hydra/issues/643)), so the package does not compile for+ that target. It publishes to Hackage and PyPI as usual.+- The breaking batch leaves three deliberate 0.18 tails, each separately tracked:+ `effects.pure` is retained provisionally pending a name decision+ ([#688](https://github.com/CategoricalData/hydra/issues/688)); the `printable` type class that would+ promote the print/parse convention into enforced dispatch awaits+ [#497](https://github.com/CategoricalData/hydra/issues/497); and the literal conversion lattice is+ gated on [#129](https://github.com/CategoricalData/hydra/issues/129) via+ [#689](https://github.com/CategoricalData/hydra/issues/689). Anticipated `TypeClassConstraint`+ variants remain open as [#686](https://github.com/CategoricalData/hydra/issues/686) — the `set`+ element type must stay orderable as variants are added.++---+ ## [0.17.5] - 2026-08-19 Point release on the 0.17.x line. Two language-surface changes lead: sum-type eliminators unify on
hydra-scala.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.38.1.+-- This file has been generated from package.yaml by hpack version 0.39.1. -- -- see: https://github.com/sol/hpack name: hydra-scala-version: 0.17.5+version: 0.17.6 synopsis: Hydra's Scala coder: emit Scala source from Hydra modules description: Hydra is an implementation of the LambdaGraph data model, which takes advantage of an isomorphism between labeled hypergraphs and typed lambda calculus: in Hydra, "graphs are programs, and programs are graphs". Scala support for Hydra category: Data@@ -40,7 +40,7 @@ build-depends: base >=4.19.0 && <4.22 , containers >=0.6.7 && <0.8- , hydra-jvm ==0.17.5- , hydra-kernel ==0.17.5+ , hydra-jvm ==0.17.6+ , hydra-kernel ==0.17.6 , scientific >=0.3.7 && <0.4 default-language: Haskell2010
src/main/haskell/Hydra/Dsl/Scala/Syntax.hs view
@@ -9,6 +9,7 @@ import qualified Hydra.Typed as Typed import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void import qualified Data.Int as I -- | DSL constructor for hydra.scala.syntax.AlternativePat
src/main/haskell/Hydra/Scala/Coder.hs view
@@ -68,6 +68,7 @@ import qualified Hydra.Variants as Variants import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void import qualified Data.Map as M import qualified Data.Set as S @@ -145,7 +146,7 @@ filteredFallback0 = Logic.ifElse (Equality.equal (Lists.length allSchemeVars) (Lists.length fallbackTypeApps)) (filterByFlags fallbackTypeApps keepFlags) fallbackTypeApps filteredFallback =- Logic.ifElse (Maps.null overgenSubst) filteredFallback0 (Lists.map (\t -> substituteTypeVarsWithTypes overgenSubst t) filteredFallback0)+ Logic.ifElse (Maps.isEmpty overgenSubst) filteredFallback0 (Lists.map (\t -> substituteTypeVarsWithTypes overgenSubst t) filteredFallback0) in (Right filteredFallback))) -- | Count the curried function parameters of a type (#589)@@ -191,7 +192,7 @@ nonSelfVars = Lists.filter (\vv -> Logic.not (Equality.equal vv inVar)) outVars safeNonSelfVars = Lists.filter (\vv -> Logic.and (Logic.not (Sets.member vv directInputVars)) (Logic.not (Equality.equal (Just vv) codVar))) nonSelfVars- in (Logic.ifElse (Logic.and (Ordering.gte selfRefCount 2) (Logic.not (Lists.null safeNonSelfVars))) (Lists.foldl (\s -> \vv -> Maps.insert vv inVar s) subst safeNonSelfVars) subst)+ in (Logic.ifElse (Logic.and (Ordering.gte selfRefCount 2) (Logic.not (Lists.isEmpty safeNonSelfVars))) (Lists.foldl (\s -> \vv -> Maps.insert vv inVar s) subst safeNonSelfVars) subst) -- | Drop N domain types from a function type, returning the remaining type dropDomains :: Int -> Core.Type -> Core.Type@@ -278,12 +279,12 @@ Graph.graphTypeVariables = (Sets.union (Sets.fromList freeTypeVars) (Graph.graphTypeVariables g))} in (Eithers.bind (Eithers.mapList (encodeTypedParam cx gWithTypeVars) zippedParams) (\sparams -> Eithers.bind (encodeTerm overlaySubs cx gWithTypeVars (extractBody term)) (\sbody -> Eithers.bind (encodeType cx g cod) (\scod -> let gForLets =- Logic.ifElse (Lists.null letBindings) gWithTypeVars (Scoping.extendGraphForLet (\g2 -> \b -> Logic.ifElse (Predicates.isComplexBinding g2 b) (Just (Core.TermLiteral (Core.LiteralBoolean True))) Nothing) gWithTypeVars (Core.Let {+ Logic.ifElse (Lists.isEmpty letBindings) gWithTypeVars (Scoping.extendGraphForLet (\g2 -> \b -> Logic.ifElse (Predicates.isComplexBinding g2 b) (Just (Core.TermLiteral (Core.LiteralBoolean True))) Nothing) gWithTypeVars (Core.Let { Core.letBindings = letBindings, Core.letBody = (Core.TermVariable (Core.Name "dummy"))})) in (Eithers.bind (Eithers.mapList (encodeLetBinding overlaySubs cx gForLets (Sets.fromList freeTypeVars)) letBindings) (\sbindings -> let defBody =- Logic.ifElse (Lists.null sbindings) sbody (Syntax.DataBlock (Syntax.BlockData {+ Logic.ifElse (Lists.isEmpty sbindings) sbody (Syntax.DataBlock (Syntax.BlockData { Syntax.blockDataStats = (Lists.concat2 sbindings [ Syntax.StatTerm sbody])})) in (Right (Syntax.StatDefn (Syntax.DefnDef (Syntax.DefDefn {@@ -311,7 +312,7 @@ unqualifiedFreeVars = Sets.fromList (Lists.filter (\n -> Logic.not (Lists.member 46 (Strings.toList (Core.unName n)))) (Sets.toList freeVars)) unresolvedVars = Sets.difference unqualifiedFreeVars (Graph.graphTypeVariables g)- in (Logic.ifElse (Sets.null unresolvedVars) (Just dom) Nothing))+ in (Logic.ifElse (Sets.isEmpty unresolvedVars) (Just dom) Nothing)) in (Eithers.bind (encodeTerm overlaySubs cx g body) (\sbody -> Eithers.bind (Optionals.match mdom (findSdom cx g meta) (\dom -> Eithers.bind (encodeType cx g dom) (\sdom -> Right (Just sdom)))) (\sdom -> Right (Utils.slambda v sbody sdom)))) Core.TermUnwrap _ -> Optionals.match arg (Eithers.bind (findSdom cx g meta) (\sdom -> Right (Utils.slambda "x" (Utils.sname "x") sdom))) (\a -> encodeTerm overlaySubs cx g a) Core.TermProject v0 ->@@ -368,7 +369,7 @@ Syntax.valDefnDecltpe = Nothing, Syntax.valDefnRhs = srhs}))))) (\ts -> let newVars = Lists.filter (\v -> Logic.not (Sets.member v outerTypeVars)) (Core.typeSchemeVariables ts)- useDef = Logic.or isFn (Logic.not (Lists.null newVars))+ useDef = Logic.or isFn (Logic.not (Lists.isEmpty newVars)) in (Logic.ifElse useDef (encodeLocalDef overlaySubs cx g outerTypeVars bname bterm (Core.typeSchemeBody ts)) (Eithers.bind (encodeTerm overlaySubs cx g bterm) (\srhs -> Eithers.bind (encodeType cx g (Core.typeSchemeBody ts)) (\styp -> Right (Syntax.StatDefn (Syntax.DefnVal (Syntax.ValDefn { Syntax.valDefnMods = [ Syntax.ModLazy],@@ -385,7 +386,7 @@ case av of Core.LiteralBinary v0 -> Right (Syntax.LitBytes (Literals.binaryToBytes v0)) Core.LiteralBoolean v0 -> Right (Syntax.LitBoolean v0)- Core.LiteralDecimal v0 -> Right (Syntax.LitString (Literals.showDecimal v0))+ Core.LiteralDecimal v0 -> Right (Syntax.LitString (Literals.printDecimal v0)) Core.LiteralFloat v0 -> case v0 of Core.FloatValueFloat32 v1 -> Right (Syntax.LitFloat v1) Core.FloatValueFloat64 v1 -> Right (Syntax.LitDouble v1)@@ -430,12 +431,12 @@ Graph.graphTypeVariables = (Sets.union allTypeVars (Graph.graphTypeVariables g))} in (Eithers.bind (Eithers.mapList (encodeTypedParam cx gWithTypeVars) zippedParams) (\sparams -> Eithers.bind (encodeTerm overlaySubs cx gWithTypeVars (extractBody term)) (\sbody -> Eithers.bind (encodeType cx gWithTypeVars cod) (\scod -> let gForLets =- Logic.ifElse (Lists.null letBindings) gWithTypeVars (Scoping.extendGraphForLet (\g2 -> \b -> Logic.ifElse (Predicates.isComplexBinding g2 b) (Just (Core.TermLiteral (Core.LiteralBoolean True))) Nothing) gWithTypeVars (Core.Let {+ Logic.ifElse (Lists.isEmpty letBindings) gWithTypeVars (Scoping.extendGraphForLet (\g2 -> \b -> Logic.ifElse (Predicates.isComplexBinding g2 b) (Just (Core.TermLiteral (Core.LiteralBoolean True))) Nothing) gWithTypeVars (Core.Let { Core.letBindings = letBindings, Core.letBody = (Core.TermVariable (Core.Name "dummy"))})) in (Eithers.bind (Eithers.mapList (encodeLetBinding overlaySubs cx gForLets allTypeVars) letBindings) (\sbindings -> let defBody =- Logic.ifElse (Lists.null sbindings) sbody (Syntax.DataBlock (Syntax.BlockData {+ Logic.ifElse (Lists.isEmpty sbindings) sbody (Syntax.DataBlock (Syntax.BlockData { Syntax.blockDataStats = (Lists.concat2 sbindings [ Syntax.StatTerm sbody])})) in (Right (Syntax.StatDefn (Syntax.DefnDef (Syntax.DefDefn {@@ -514,9 +515,9 @@ litData]) Core.LiteralInteger v1 -> case v1 of Core.IntegerValueBigint v2 -> Right (Utils.sapply (Utils.sname "BigInt") [- Syntax.DataLit (Syntax.LitString (Literals.showBigint v2))])+ Syntax.DataLit (Syntax.LitString (Literals.printBigint v2))]) Core.IntegerValueUint64 v2 -> Right (Utils.sapply (Utils.sname "BigInt") [- Syntax.DataLit (Syntax.LitString (Literals.showBigint (Literals.uint64ToBigint v2)))])+ Syntax.DataLit (Syntax.LitString (Literals.printBigint (Literals.uint64ToBigint v2)))]) _ -> Right litData _ -> Right litData) Core.TermMap v0 -> Eithers.bind (Eithers.mapList (\kv -> Eithers.bind (encodeTerm overlaySubs cx g (Pairs.first kv)) (\sk -> Eithers.bind (encodeTerm overlaySubs cx g (Pairs.second kv)) (\sv -> Right (Utils.sassign sk sv)))) (Maps.toList v0)) (\spairs -> Right (Utils.sapply (Utils.sname "Map") spairs))@@ -588,7 +589,7 @@ _ -> False freeTypeVarsInTyp = Lists.filter (\v -> Logic.not (Lists.member 46 (Strings.toList (Core.unName v)))) (Sets.toList (Variables.freeVariablesInType typ_))- in (Logic.ifElse isFunctionType (encodeComplexTermDef overlaySubs cx g lname term typ_) (Logic.ifElse (Lists.null freeTypeVarsInTyp) (Eithers.bind (encodeType cx g typ_) (\stype -> Eithers.bind (encodeTerm overlaySubs cx g term) (\rhs -> Right (Syntax.StatDefn (Syntax.DefnVal (Syntax.ValDefn {+ in (Logic.ifElse isFunctionType (encodeComplexTermDef overlaySubs cx g lname term typ_) (Logic.ifElse (Lists.isEmpty freeTypeVarsInTyp) (Eithers.bind (encodeType cx g typ_) (\stype -> Eithers.bind (encodeTerm overlaySubs cx g term) (\rhs -> Right (Syntax.StatDefn (Syntax.DefnVal (Syntax.ValDefn { Syntax.valDefnMods = [ Syntax.ModLazy], Syntax.valDefnPats = [@@ -960,7 +961,7 @@ Core.TypeRecord v0 -> Equality.equal (Lists.length v0) 0 _ -> False parentType =- Logic.ifElse (Lists.null tparams) (Syntax.TypeRef (Syntax.RefTypeName (Syntax.NameType {+ Logic.ifElse (Lists.isEmpty tparams) (Syntax.TypeRef (Syntax.RefTypeName (Syntax.NameType { Syntax.nameTypeValue = parentName}))) (Syntax.TypeApply (Syntax.ApplyType { Syntax.applyTypeTpe = (Syntax.TypeRef (Syntax.RefTypeName (Syntax.NameType { Syntax.nameTypeValue = parentName}))),
src/main/haskell/Hydra/Scala/Language.hs view
@@ -37,6 +37,7 @@ import qualified Hydra.Variants as Variants import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void import qualified Data.Set as S -- | Language constraints for Scala
src/main/haskell/Hydra/Scala/Serde.hs view
@@ -45,6 +45,7 @@ import qualified Hydra.Variants as Variants import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void -- | Convert a case clause to an expression caseToExpr :: Syntax.Case -> Ast.Expr@@ -85,7 +86,7 @@ let name = Syntax.paramDataName dp stype = Syntax.paramDataDecltpe dp in (Serialization.noSep (Optionals.givens [- Optionals.pure (nameToExpr name),+ Optionals.given (nameToExpr name), (Optionals.map (\t -> Serialization.spaceSep [ Serialization.cst ":", (typeToExpr t)]) stype)]))@@ -116,7 +117,7 @@ scod = Syntax.defDefnDecltpe v0 body = Syntax.defDefnBody v0 tparamsExpr =- Logic.ifElse (Lists.null tparams) Nothing (Optionals.pure (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams)))+ Logic.ifElse (Lists.isEmpty tparams) Nothing (Optionals.given (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams))) scodExpr = Optionals.map (\t -> Serialization.spaceSep [ Serialization.cst ":",@@ -125,10 +126,10 @@ nameAndParams = Serialization.noSep (Optionals.givens (Lists.concat [ [- Optionals.pure (dataNameToExpr name)],+ Optionals.given (dataNameToExpr name)], [ tparamsExpr],- (Lists.map (\pe -> Optionals.pure pe) paramssExprs),+ (Lists.map (\pe -> Optionals.given pe) paramssExprs), [ scodExpr]])) bodyExpr = termToExpr body@@ -149,11 +150,11 @@ tparams = Syntax.typeDefnTparams v0 body = Syntax.typeDefnBody v0 in (Serialization.spaceSep (Optionals.givens [- Optionals.pure (Serialization.cst "type"),- (Optionals.pure (typeNameToExpr name)),- (Logic.ifElse (Lists.null tparams) Nothing (Optionals.pure (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams)))),- (Optionals.pure (Serialization.cst "=")),- (Optionals.pure (typeToExpr body))]))+ Optionals.given (Serialization.cst "type"),+ (Optionals.given (typeNameToExpr name)),+ (Logic.ifElse (Lists.isEmpty tparams) Nothing (Optionals.given (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams)))),+ (Optionals.given (Serialization.cst "=")),+ (Optionals.given (typeToExpr body))])) Syntax.DefnVal v0 -> let mods = Syntax.valDefnMods v0 pats = Syntax.valDefnPats v0@@ -169,7 +170,7 @@ Optionals.match typ (Serialization.cst nameStr) (\t -> Serialization.spaceSep [ Serialization.cst (Strings.concat2 nameStr ":"), (typeToExpr t)])- valKeyword = Logic.ifElse (Lists.null mods) "val" "lazy val"+ valKeyword = Logic.ifElse (Lists.isEmpty mods) "val" "lazy val" in (Serialization.spaceSep [ Serialization.cst valKeyword, nameAndType,@@ -182,12 +183,12 @@ ctor = Syntax.classDefnCtor v0 paramss = Syntax.primaryCtorParamss ctor tparamsExpr =- Logic.ifElse (Lists.null tparams) Nothing (Optionals.pure (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams)))+ Logic.ifElse (Lists.isEmpty tparams) Nothing (Optionals.given (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams))) paramsExpr =- Logic.ifElse (Lists.null paramss) Nothing (Optionals.pure (Serialization.parenListAdaptive (Lists.map dataParamToExpr (Lists.concat paramss))))+ Logic.ifElse (Lists.isEmpty paramss) Nothing (Optionals.given (Serialization.parenListAdaptive (Lists.map dataParamToExpr (Lists.concat paramss)))) nameAndParams = Serialization.noSep (Optionals.givens [- Optionals.pure (typeNameToExpr name),+ Optionals.given (typeNameToExpr name), tparamsExpr, paramsExpr]) in (Serialization.spaceSep (Lists.concat [@@ -204,8 +205,8 @@ Serialization.spaceSep [ Serialization.cst "enum", (Serialization.noSep (Optionals.givens [- Optionals.pure (typeNameToExpr name),- (Logic.ifElse (Lists.null tparams) Nothing (Optionals.pure (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams))))])),+ Optionals.given (typeNameToExpr name),+ (Logic.ifElse (Lists.isEmpty tparams) Nothing (Optionals.given (Serialization.bracketList Serialization.inlineStyle (Lists.map typeParamToExpr tparams))))])), (Serialization.cst ":")] enumCases = Lists.map (\s -> Serialization.spaceSep [@@ -222,9 +223,9 @@ paramss = Syntax.primaryCtorParamss ctor allParams = Lists.concat paramss params =- Logic.ifElse (Lists.null allParams) (Serialization.cst "") (Serialization.parenListAdaptive (Lists.map dataParamToExpr allParams))+ Logic.ifElse (Lists.isEmpty allParams) (Serialization.cst "") (Serialization.parenListAdaptive (Lists.map dataParamToExpr allParams)) extendsClause =- Logic.ifElse (Lists.null inits) (Serialization.cst "") (Serialization.spaceSep [+ Logic.ifElse (Lists.isEmpty inits) (Serialization.cst "") (Serialization.spaceSep [ Serialization.cst "extends", (Serialization.commaSep Serialization.inlineStyle (Lists.map initToExpr inits))]) in (Serialization.spaceSep [@@ -267,7 +268,7 @@ case ref of Syntax.RefDataName v0 -> Syntax.unPredefString (Syntax.nameDataValue v0) forImportees =- Logic.ifElse (Lists.null importees) (Serialization.cst "") (Logic.ifElse (Equality.equal (Lists.length importees) 1) (Optionals.withDefault (Serialization.cst "") (Optionals.map (\firstImp -> Serialization.noSep [+ Logic.ifElse (Lists.isEmpty importees) (Serialization.cst "") (Logic.ifElse (Equality.equal (Lists.length importees) 1) (Optionals.withDefault (Serialization.cst "") (Optionals.map (\firstImp -> Serialization.noSep [ Serialization.cst ".", case firstImp of Syntax.ImporteeWildcard -> Serialization.cst "*"@@ -293,15 +294,15 @@ litToExpr lit = case lit of Syntax.LitBoolean v0 -> Serialization.cst (Logic.ifElse v0 "true" "false")- Syntax.LitByte v0 -> Serialization.cst (Strings.concat2 (Literals.showInt8 v0) ".toByte")- Syntax.LitShort v0 -> Serialization.cst (Strings.concat2 (Literals.showInt16 v0) ".toShort")- Syntax.LitInt v0 -> Serialization.cst (Literals.showInt32 v0)- Syntax.LitLong v0 -> Serialization.cst (Strings.concat2 (Literals.showInt64 v0) "L")- Syntax.LitFloat v0 -> Serialization.cst (scalaFloatLiteralText "Float" "f" (Literals.showFloat32 v0))- Syntax.LitDouble v0 -> Serialization.cst (scalaFloatLiteralText "Double" "" (Literals.showFloat64 v0))+ Syntax.LitByte v0 -> Serialization.cst (Strings.concat2 (Literals.printInt8 v0) ".toByte")+ Syntax.LitShort v0 -> Serialization.cst (Strings.concat2 (Literals.printInt16 v0) ".toShort")+ Syntax.LitInt v0 -> Serialization.cst (Literals.printInt32 v0)+ Syntax.LitLong v0 -> Serialization.cst (Strings.concat2 (Literals.printInt64 v0) "L")+ Syntax.LitFloat v0 -> Serialization.cst (scalaFloatLiteralText "Float" "f" (Literals.printFloat32 v0))+ Syntax.LitDouble v0 -> Serialization.cst (scalaFloatLiteralText "Double" "" (Literals.printFloat64 v0)) Syntax.LitUnit -> Serialization.cst "()" Syntax.LitString v0 -> Serialization.cst (Strings.concat2 "\"" (Strings.concat2 (Serde.escapeJavaString v0) "\""))- Syntax.LitBytes v0 -> Serialization.cst (Strings.concat2 "Array[Byte](" (Strings.concat2 (Strings.join ", " (Lists.map (\b -> Strings.concat2 (Literals.showInt32 b) ".toByte") v0)) ")"))+ Syntax.LitBytes v0 -> Serialization.cst (Strings.concat2 "Array[Byte](" (Strings.concat2 (Strings.join ", " (Lists.map (\b -> Strings.concat2 (Literals.printInt32 b) ".toByte") v0)) ")")) _ -> Serialization.cst "TODO:literal" -- | The match operator@@ -342,7 +343,7 @@ Syntax.PatExtract v0 -> let fun = Syntax.extractPatFun v0 args = Syntax.extractPatArgs v0- in (Logic.ifElse (Lists.null args) (termToExpr fun) (Serialization.noSep [+ in (Logic.ifElse (Lists.isEmpty args) (termToExpr fun) (Serialization.noSep [ termToExpr fun, (Serialization.parenListAdaptive (Lists.map patToExpr args))])) Syntax.PatVar v0 -> dataNameToExpr (Syntax.varPatName v0)
src/main/haskell/Hydra/Scala/Syntax.hs view
@@ -7,6 +7,7 @@ import qualified Hydra.Core as Core import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void import qualified Data.Int as I -- | A wrapper for strings used in scala.Predef contexts.
src/main/haskell/Hydra/Scala/Utils.hs view
@@ -47,6 +47,7 @@ import qualified Hydra.Variants as Variants import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, lines, map, pure, sum, unlines) import qualified Data.Scientific as Sci+import Data.Void import qualified Data.Set as S -- | Extract the name from a type, if it is a named type@@ -72,7 +73,7 @@ -- | Apply explicit type parameters to a Scala expression (e.g. f[A, B]); a no-op for an empty type-arg list (#589) sapplyTypes :: Syntax.Data -> [Syntax.Type] -> Syntax.Data sapplyTypes fun typeArgs =- Logic.ifElse (Lists.null typeArgs) fun (+ Logic.ifElse (Lists.isEmpty typeArgs) fun ( let typeToStr = \t -> typeToString t typeStrings = Lists.map typeToStr typeArgs typeArgStr =