packages feed

hydra-lisp 0.17.6 → 0.17.7

raw patch · 7 files changed

+547/−5 lines, 7 filesdep ~hydra-kernelPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: hydra-kernel

API changes (from Hackage documentation)

+ Hydra.Dsl.Lisp.Syntax: decimalLiteral :: TypedTerm String -> TypedTerm DecimalLiteral
+ Hydra.Dsl.Lisp.Syntax: decimalLiteralDecimalLiteral :: TypedName DecimalLiteral
+ Hydra.Dsl.Lisp.Syntax: decimalLiteralDigits :: TypedTerm DecimalLiteral -> TypedTerm String
+ Hydra.Dsl.Lisp.Syntax: decimalLiteralWithDigits :: TypedTerm DecimalLiteral -> TypedTerm String -> TypedTerm DecimalLiteral
+ Hydra.Dsl.Lisp.Syntax: literalDecimal :: TypedTerm DecimalLiteral -> TypedTerm Literal
+ Hydra.Lisp.Language: clojureLanguage :: Language
+ Hydra.Lisp.Language: commonLispLanguage :: Language
+ Hydra.Lisp.Language: emacsLispLanguage :: Language
+ Hydra.Lisp.Language: schemeLanguage :: Language
+ Hydra.Lisp.Serde: decimalDigitsAndScale :: String -> ((String, String), Int)
+ Hydra.Lisp.Syntax: DecimalLiteral :: String -> DecimalLiteral
+ Hydra.Lisp.Syntax: LiteralDecimal :: DecimalLiteral -> Literal
+ Hydra.Lisp.Syntax: [decimalLiteralDigits] :: DecimalLiteral -> String
+ Hydra.Lisp.Syntax: _DecimalLiteral :: Name
+ Hydra.Lisp.Syntax: _DecimalLiteral_digits :: Name
+ Hydra.Lisp.Syntax: _Literal_decimal :: Name
+ Hydra.Lisp.Syntax: data DecimalLiteral
+ Hydra.Lisp.Syntax: instance GHC.Classes.Eq Hydra.Lisp.Syntax.DecimalLiteral
+ Hydra.Lisp.Syntax: instance GHC.Classes.Ord Hydra.Lisp.Syntax.DecimalLiteral
+ Hydra.Lisp.Syntax: instance GHC.Read.Read Hydra.Lisp.Syntax.DecimalLiteral
+ Hydra.Lisp.Syntax: instance GHC.Show.Show Hydra.Lisp.Syntax.DecimalLiteral

Files

CHANGELOG.md view
@@ -15,6 +15,88 @@  --- +## [0.17.7] - 2026-09-14++Correctness-hardening point release on the 0.17.x line, consolidating the 0.17.6 breaking batch. It+closes a family of silent cross-host correctness bugs in the equality, ordering, integer-narrowing+and string primitives, and adds the systematic test coverage that exposed them. No kernel-surface+breaking changes.++### Highlights++- **Silent-wrong primitives corrected across hosts**+  ([#745](https://github.com/CategoricalData/hydra/issues/745),+  [#742](https://github.com/CategoricalData/hydra/issues/742)): new shared cross-host fixtures+  uncovered ~a dozen primitives (`equal`/`compare` on collections, float equality, `bigintToIntN`+  narrowing, `parseUint*` bounds, astral-plane string ops) that returned wrong results on one or more+  non-Haskell hosts while appearing to pass. All are now correct and verified per-host against the+  Haskell reference oracle.+- **Systematic test-coverage hardening**+  ([#749](https://github.com/CategoricalData/hydra/issues/749)): new kernel coverage for previously+  untested primitive behavior (equality/ordering collection depth, `notEqual`, `functions.const`/`flip`),+  which drove wiring those primitives into every host's default-implementation fallback.+- **Scale-preserving decimals across every lossy-double host**+  ([#727](https://github.com/CategoricalData/hydra/issues/727),+  [#719](https://github.com/CategoricalData/hydra/issues/719)): `Literal.decimal` gains a real+  scale-preserving representation (coefficient + scale) in the Scheme, Emacs Lisp, Common Lisp and+  TypeScript runtimes and coders, and the generated `Literal.Decimal` `equals`/`compareTo` on Java,+  Python and Scala stop ignoring scale. The `scaleDistinctTestNames` skip list — which had been+  masking the gap on five hosts — is deleted, so decimal scale is now verified everywhere rather+  than excused.++### Bug fixes++- **[#745](https://github.com/CategoricalData/hydra/issues/745)** silent-wrong equality/ordering,+  `bigintToIntN` narrowing, `parseUint32/64` bounds, and astral-plane `charAt`/`splitOn`/`compare`+  across the eight non-Haskell hosts.+- **[#742](https://github.com/CategoricalData/hydra/issues/742)** structural `equal`/`compare` on+  maps, sets and nested decimals no longer falls back to scale-blind or print-based comparison+  (including a hand-inlined Scala primitive that shadowed the overlay fix).+- **[#743](https://github.com/CategoricalData/hydra/issues/743)** kernel JSON decoder now rejects an+  `Either` object carrying both `left` and `right` keys instead of silently resolving one arm.+- **[#740](https://github.com/CategoricalData/hydra/issues/740)** the recursive parametric union decoder+  now emits an explicit type application instead of an untyped lambda, so recursive parametric-union+  types generate and compile on the Java host; also fixes `update-json-kernel` reconcile to build a+  complete inference universe so drifted kernel modules re-infer.+- **[#720](https://github.com/CategoricalData/hydra/issues/720)** Python's+  `hydra.lib.equality`/`ordering` did not satisfy IEEE `totalOrder` for floats, mis-ordering `NaN`+  and signed zero.+- **[#722](https://github.com/CategoricalData/hydra/issues/722)** two `kernelDefaultCoreProfile`+  correctness defects: rule ids that referred to rules no longer present, and a stubbed+  `isValidName` that accepted every name.++### Improvements++- **[#749](https://github.com/CategoricalData/hydra/issues/749)** `notEqual`/`const`/`flip` wired+  into each host's `#609` default-implementation fallback; orphaned Avro coder test suite recovered.+- **[#730](https://github.com/CategoricalData/hydra/issues/730)** a shared `~/.stack` build slot+  (`bin/with-stack-slot.sh`) replaces the pgrep slot mechanic, serializing concurrent GHC builds+  across the fleet behind a real mutex. The wrapper is now portable to macOS: `flock(1)` is+  util-linux and absent there, so it is emulated via Perl's `flock()` where missing, and the+  GNU-only `date -Is`/`date -d` calls are replaced with portable equivalents. Its bypass path also+  no longer re-execs forever. Without these, every entry point that routes through the slot —+  `bin/sync.sh`, `bin/test.sh`, `bin/run-bootstrapping-demo.sh` and `bin/prepare-release.sh` —+  failed immediately on macOS.+- **[#600](https://github.com/CategoricalData/hydra/issues/600)** the five published TypeScript+  packages are subpath-import-only (uniform export surface).+- **[#716](https://github.com/CategoricalData/hydra/issues/716)** `hydra.paths` reshaped onto the+  term-graph model (`TermGraph`/`TypeGraph`), aligning path steps with the term and type grammars+  and adding the link view of a graph; `mapKey`/`mapValue` collapse into a single `mapEntry` step.+- **[#701](https://github.com/CategoricalData/hydra/issues/701)** module cache freshness is now a+  Merkle hash over each module's dependency closure, so a change deep in the closure correctly+  invalidates dependents.+- **[#559](https://github.com/CategoricalData/hydra/issues/559)** host-agnostic build: the+  remaining hand-coded host build logic is promoted into `hydra.build.*`, with Java as the+  definitive second host.+- **[#721](https://github.com/CategoricalData/hydra/issues/721)** `checkNestedModuleNames` packaging+  check enforces the module-namespace no-prefix rule.++### Documentation++- **[#508](https://github.com/CategoricalData/hydra/issues/508)** de-Claude-speak documentation pass:+  style-guide section added, stale paths and dead links repaired, agent-operations wiki pages moved+  into `claude/`, and a `getting-started.md` guardrail against re-adding a TypeScript root export.+ ## [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
hydra-lisp.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           hydra-lisp-version:        0.17.6+version:        0.17.7 synopsis:       Hydra's Lisp coder: emit Clojure/Scheme/Common-Lisp/Emacs-Lisp source 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". Lisp support for Hydra (shared across Clojure, Scheme, Common Lisp, and Emacs Lisp) category:       Data@@ -39,6 +39,6 @@   build-depends:       base >=4.19.0 && <4.22     , containers >=0.6.7 && <0.8-    , hydra-kernel ==0.17.6+    , hydra-kernel ==0.17.7     , scientific >=0.3.7 && <0.4   default-language: Haskell2010
src/main/haskell/Hydra/Dsl/Lisp/Syntax.hs view
@@ -893,6 +893,39 @@               Core.projectionFieldName = (Core.Name "arguments")})),             Core.applicationArgument = (Typed.unTypedTerm original)}))}]})) +-- | DSL constructor for hydra.lisp.syntax.DecimalLiteral+decimalLiteral :: Typed.TypedTerm String -> Typed.TypedTerm Syntax.DecimalLiteral+decimalLiteral digits =+    Typed.TypedTerm (Core.TermRecord (Core.Record {+      Core.recordTypeName = (Core.Name "hydra.lisp.syntax.DecimalLiteral"),+      Core.recordFields = [+        Core.Field {+          Core.fieldName = (Core.Name "digits"),+          Core.fieldTerm = (Typed.unTypedTerm digits)}]}))++-- | DSL name token for hydra.lisp.syntax.DecimalLiteral+decimalLiteralDecimalLiteral :: Typed.TypedName Syntax.DecimalLiteral+decimalLiteralDecimalLiteral = Typed.TypedName (Core.Name "hydra.lisp.syntax.DecimalLiteral")++-- | DSL accessor for the digits field of hydra.lisp.syntax.DecimalLiteral+decimalLiteralDigits :: Typed.TypedTerm Syntax.DecimalLiteral -> Typed.TypedTerm String+decimalLiteralDigits x =+    Typed.TypedTerm (Core.TermApplication (Core.Application {+      Core.applicationFunction = (Core.TermProject (Core.Projection {+        Core.projectionTypeName = (Core.Name "hydra.lisp.syntax.DecimalLiteral"),+        Core.projectionFieldName = (Core.Name "digits")})),+      Core.applicationArgument = (Typed.unTypedTerm x)}))++-- | DSL updater for the digits field of hydra.lisp.syntax.DecimalLiteral+decimalLiteralWithDigits :: Typed.TypedTerm Syntax.DecimalLiteral -> Typed.TypedTerm String -> Typed.TypedTerm Syntax.DecimalLiteral+decimalLiteralWithDigits original newVal =+    Typed.TypedTerm (Core.TermRecord (Core.Record {+      Core.recordTypeName = (Core.Name "hydra.lisp.syntax.DecimalLiteral"),+      Core.recordFields = [+        Core.Field {+          Core.fieldName = (Core.Name "digits"),+          Core.fieldTerm = (Typed.unTypedTerm newVal)}]}))+ -- | DSL constructor for hydra.lisp.syntax.DestructuringBinding destructuringBinding :: Typed.TypedTerm Syntax.DestructuringPattern -> Typed.TypedTerm Syntax.Expression -> Typed.TypedTerm Syntax.DestructuringBinding destructuringBinding pattern value =@@ -2833,6 +2866,15 @@       Core.injectionTypeName = (Core.Name "hydra.lisp.syntax.Literal"),       Core.injectionField = Core.Field {         Core.fieldName = (Core.Name "character"),+        Core.fieldTerm = (Typed.unTypedTerm x)}}))++-- | DSL injection for the decimal variant of hydra.lisp.syntax.Literal+literalDecimal :: Typed.TypedTerm Syntax.DecimalLiteral -> Typed.TypedTerm Syntax.Literal+literalDecimal x =+    Typed.TypedTerm (Core.TermInject (Core.Injection {+      Core.injectionTypeName = (Core.Name "hydra.lisp.syntax.Literal"),+      Core.injectionField = Core.Field {+        Core.fieldName = (Core.Name "decimal"),         Core.fieldTerm = (Typed.unTypedTerm x)}}))  -- | DSL injection for the float variant of hydra.lisp.syntax.Literal
src/main/haskell/Hydra/Lisp/Coder.hs view
@@ -216,9 +216,8 @@ encodeLiteral lit =     case lit of       Core.LiteralBoolean v0 -> Syntax.ExpressionLiteral (Syntax.LiteralBoolean v0)-      Core.LiteralDecimal v0 -> Syntax.ExpressionLiteral (Syntax.LiteralFloat (Syntax.FloatLiteral {-        Syntax.floatLiteralValue = (Literals.decimalToFloat64 v0),-        Syntax.floatLiteralPrecision = Nothing}))+      Core.LiteralDecimal v0 -> Syntax.ExpressionLiteral (Syntax.LiteralDecimal (Syntax.DecimalLiteral {+        Syntax.decimalLiteralDigits = (Literals.printDecimal v0)}))       Core.LiteralString v0 -> Syntax.ExpressionLiteral (Syntax.LiteralString v0)       Core.LiteralFloat v0 -> case v0 of         Core.FloatValueFloat32 v1 -> Syntax.ExpressionLiteral (Syntax.LiteralFloat (Syntax.FloatLiteral {
src/main/haskell/Hydra/Lisp/Language.hs view
@@ -41,6 +41,264 @@ import Data.Void import qualified Data.Set as S +-- | Language constraints for Clojure+clojureLanguage :: Coders.Language+clojureLanguage =+    Coders.Language {+      Coders.languageName = (Coders.LanguageName "hydra.lisp"),+      Coders.languageConstraints = Coders.LanguageConstraints {+        Coders.languageConstraintsLiteralVariants = literalVariants,+        Coders.languageConstraintsFloatTypes = floatTypes,+        Coders.languageConstraintsIntegerTypes = integerTypes,+        Coders.languageConstraintsTermVariants = termVariants,+        Coders.languageConstraintsTypeVariants = typeVariants,+        Coders.languageConstraintsTypes = typePredicate},+      Coders.languageSupportedFeatures = (Sets.fromList [+        Coders.LanguageFeaturePartialApplication,+        Coders.LanguageFeatureNestedCaseStatements,+        Coders.LanguageFeatureNestedPolymorphicLetBindings]),+      Coders.languageCaseConventions = Coders.CaseConventions {+        Coders.caseConventionsConstant = Util.CaseConventionUpperSnake,+        Coders.caseConventionsDirectory = Util.CaseConventionLowerSnake,+        Coders.caseConventionsEnumValue = Util.CaseConventionLowerSnake,+        Coders.caseConventionsField = Util.CaseConventionLowerSnake,+        Coders.caseConventionsFile = Util.CaseConventionLowerSnake,+        Coders.caseConventionsModule = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTerm = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTermVariable = Util.CaseConventionLowerSnake,+        Coders.caseConventionsType = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTypeVariable = Util.CaseConventionLowerSnake},+      Coders.languageDefaultFileExtension = (File.FileExtension "clj")}+  where+    literalVariants =+        Sets.fromList [+          Variants.LiteralVariantBinary,+          Variants.LiteralVariantBoolean,+          Variants.LiteralVariantDecimal,+          Variants.LiteralVariantFloat,+          Variants.LiteralVariantInteger,+          Variants.LiteralVariantString]+    floatTypes = Sets.fromList [+      Core.FloatTypeFloat64]+    integerTypes = Sets.fromList [+      Core.IntegerTypeBigint]+    termVariants =+        Sets.fromList [+          Variants.TermVariantAnnotated,+          Variants.TermVariantApplication,+          Variants.TermVariantEither,+          Variants.TermVariantCases,+          Variants.TermVariantLambda,+          Variants.TermVariantProject,+          Variants.TermVariantUnwrap,+          Variants.TermVariantTypeApplication,+          Variants.TermVariantTypeLambda,+          Variants.TermVariantLet,+          Variants.TermVariantList,+          Variants.TermVariantLiteral,+          Variants.TermVariantMap,+          Variants.TermVariantOptional,+          Variants.TermVariantPair,+          Variants.TermVariantRecord,+          Variants.TermVariantSet,+          Variants.TermVariantInject,+          Variants.TermVariantUnit,+          Variants.TermVariantVariable,+          Variants.TermVariantWrap]+    typeVariants =+        Sets.fromList [+          Variants.TypeVariantAnnotated,+          Variants.TypeVariantApplication,+          Variants.TypeVariantEither,+          Variants.TypeVariantEffect,+          Variants.TypeVariantFunction,+          Variants.TypeVariantForall,+          Variants.TypeVariantList,+          Variants.TypeVariantLiteral,+          Variants.TypeVariantMap,+          Variants.TypeVariantOptional,+          Variants.TypeVariantPair,+          Variants.TypeVariantRecord,+          Variants.TypeVariantSet,+          Variants.TypeVariantUnion,+          Variants.TypeVariantUnit,+          Variants.TypeVariantVariable,+          Variants.TypeVariantVoid,+          Variants.TypeVariantWrap]+    typePredicate = \_ -> True++-- | Language constraints for Common Lisp+commonLispLanguage :: Coders.Language+commonLispLanguage =+    Coders.Language {+      Coders.languageName = (Coders.LanguageName "hydra.lisp"),+      Coders.languageConstraints = Coders.LanguageConstraints {+        Coders.languageConstraintsLiteralVariants = literalVariants,+        Coders.languageConstraintsFloatTypes = floatTypes,+        Coders.languageConstraintsIntegerTypes = integerTypes,+        Coders.languageConstraintsTermVariants = termVariants,+        Coders.languageConstraintsTypeVariants = typeVariants,+        Coders.languageConstraintsTypes = typePredicate},+      Coders.languageSupportedFeatures = (Sets.fromList [+        Coders.LanguageFeaturePartialApplication,+        Coders.LanguageFeatureNestedCaseStatements,+        Coders.LanguageFeatureNestedPolymorphicLetBindings]),+      Coders.languageCaseConventions = Coders.CaseConventions {+        Coders.caseConventionsConstant = Util.CaseConventionUpperSnake,+        Coders.caseConventionsDirectory = Util.CaseConventionLowerSnake,+        Coders.caseConventionsEnumValue = Util.CaseConventionLowerSnake,+        Coders.caseConventionsField = Util.CaseConventionLowerSnake,+        Coders.caseConventionsFile = Util.CaseConventionLowerSnake,+        Coders.caseConventionsModule = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTerm = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTermVariable = Util.CaseConventionLowerSnake,+        Coders.caseConventionsType = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTypeVariable = Util.CaseConventionLowerSnake},+      Coders.languageDefaultFileExtension = (File.FileExtension "lisp")}+  where+    literalVariants =+        Sets.fromList [+          Variants.LiteralVariantBinary,+          Variants.LiteralVariantBoolean,+          Variants.LiteralVariantDecimal,+          Variants.LiteralVariantFloat,+          Variants.LiteralVariantInteger,+          Variants.LiteralVariantString]+    floatTypes = Sets.fromList [+      Core.FloatTypeFloat64]+    integerTypes = Sets.fromList [+      Core.IntegerTypeBigint]+    termVariants =+        Sets.fromList [+          Variants.TermVariantAnnotated,+          Variants.TermVariantApplication,+          Variants.TermVariantEither,+          Variants.TermVariantCases,+          Variants.TermVariantLambda,+          Variants.TermVariantProject,+          Variants.TermVariantUnwrap,+          Variants.TermVariantTypeApplication,+          Variants.TermVariantTypeLambda,+          Variants.TermVariantLet,+          Variants.TermVariantList,+          Variants.TermVariantLiteral,+          Variants.TermVariantMap,+          Variants.TermVariantOptional,+          Variants.TermVariantPair,+          Variants.TermVariantRecord,+          Variants.TermVariantSet,+          Variants.TermVariantInject,+          Variants.TermVariantUnit,+          Variants.TermVariantVariable,+          Variants.TermVariantWrap]+    typeVariants =+        Sets.fromList [+          Variants.TypeVariantAnnotated,+          Variants.TypeVariantApplication,+          Variants.TypeVariantEither,+          Variants.TypeVariantEffect,+          Variants.TypeVariantFunction,+          Variants.TypeVariantForall,+          Variants.TypeVariantList,+          Variants.TypeVariantLiteral,+          Variants.TypeVariantMap,+          Variants.TypeVariantOptional,+          Variants.TypeVariantPair,+          Variants.TypeVariantRecord,+          Variants.TypeVariantSet,+          Variants.TypeVariantUnion,+          Variants.TypeVariantUnit,+          Variants.TypeVariantVariable,+          Variants.TypeVariantVoid,+          Variants.TypeVariantWrap]+    typePredicate = \_ -> True++-- | Language constraints for Emacs Lisp+emacsLispLanguage :: Coders.Language+emacsLispLanguage =+    Coders.Language {+      Coders.languageName = (Coders.LanguageName "hydra.lisp"),+      Coders.languageConstraints = Coders.LanguageConstraints {+        Coders.languageConstraintsLiteralVariants = literalVariants,+        Coders.languageConstraintsFloatTypes = floatTypes,+        Coders.languageConstraintsIntegerTypes = integerTypes,+        Coders.languageConstraintsTermVariants = termVariants,+        Coders.languageConstraintsTypeVariants = typeVariants,+        Coders.languageConstraintsTypes = typePredicate},+      Coders.languageSupportedFeatures = (Sets.fromList [+        Coders.LanguageFeaturePartialApplication,+        Coders.LanguageFeatureNestedCaseStatements,+        Coders.LanguageFeatureNestedPolymorphicLetBindings]),+      Coders.languageCaseConventions = Coders.CaseConventions {+        Coders.caseConventionsConstant = Util.CaseConventionUpperSnake,+        Coders.caseConventionsDirectory = Util.CaseConventionLowerSnake,+        Coders.caseConventionsEnumValue = Util.CaseConventionLowerSnake,+        Coders.caseConventionsField = Util.CaseConventionLowerSnake,+        Coders.caseConventionsFile = Util.CaseConventionLowerSnake,+        Coders.caseConventionsModule = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTerm = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTermVariable = Util.CaseConventionLowerSnake,+        Coders.caseConventionsType = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTypeVariable = Util.CaseConventionLowerSnake},+      Coders.languageDefaultFileExtension = (File.FileExtension "el")}+  where+    literalVariants =+        Sets.fromList [+          Variants.LiteralVariantBinary,+          Variants.LiteralVariantBoolean,+          Variants.LiteralVariantDecimal,+          Variants.LiteralVariantFloat,+          Variants.LiteralVariantInteger,+          Variants.LiteralVariantString]+    floatTypes = Sets.fromList [+      Core.FloatTypeFloat64]+    integerTypes = Sets.fromList [+      Core.IntegerTypeBigint]+    termVariants =+        Sets.fromList [+          Variants.TermVariantAnnotated,+          Variants.TermVariantApplication,+          Variants.TermVariantEither,+          Variants.TermVariantCases,+          Variants.TermVariantLambda,+          Variants.TermVariantProject,+          Variants.TermVariantUnwrap,+          Variants.TermVariantTypeApplication,+          Variants.TermVariantTypeLambda,+          Variants.TermVariantLet,+          Variants.TermVariantList,+          Variants.TermVariantLiteral,+          Variants.TermVariantMap,+          Variants.TermVariantOptional,+          Variants.TermVariantPair,+          Variants.TermVariantRecord,+          Variants.TermVariantSet,+          Variants.TermVariantInject,+          Variants.TermVariantUnit,+          Variants.TermVariantVariable,+          Variants.TermVariantWrap]+    typeVariants =+        Sets.fromList [+          Variants.TypeVariantAnnotated,+          Variants.TypeVariantApplication,+          Variants.TypeVariantEither,+          Variants.TypeVariantEffect,+          Variants.TypeVariantFunction,+          Variants.TypeVariantForall,+          Variants.TypeVariantList,+          Variants.TypeVariantLiteral,+          Variants.TypeVariantMap,+          Variants.TypeVariantOptional,+          Variants.TypeVariantPair,+          Variants.TypeVariantRecord,+          Variants.TypeVariantSet,+          Variants.TypeVariantUnion,+          Variants.TypeVariantUnit,+          Variants.TypeVariantVariable,+          Variants.TypeVariantVoid,+          Variants.TypeVariantWrap]+    typePredicate = \_ -> True+ -- | Language constraints for Lisp lispLanguage :: Coders.Language lispLanguage =@@ -346,3 +604,89 @@           "else"]     hydraLispKeywords = [       "Node"]++-- | Language constraints for Scheme (R7RS)+schemeLanguage :: Coders.Language+schemeLanguage =+    Coders.Language {+      Coders.languageName = (Coders.LanguageName "hydra.lisp"),+      Coders.languageConstraints = Coders.LanguageConstraints {+        Coders.languageConstraintsLiteralVariants = literalVariants,+        Coders.languageConstraintsFloatTypes = floatTypes,+        Coders.languageConstraintsIntegerTypes = integerTypes,+        Coders.languageConstraintsTermVariants = termVariants,+        Coders.languageConstraintsTypeVariants = typeVariants,+        Coders.languageConstraintsTypes = typePredicate},+      Coders.languageSupportedFeatures = (Sets.fromList [+        Coders.LanguageFeaturePartialApplication,+        Coders.LanguageFeatureNestedCaseStatements,+        Coders.LanguageFeatureNestedPolymorphicLetBindings]),+      Coders.languageCaseConventions = Coders.CaseConventions {+        Coders.caseConventionsConstant = Util.CaseConventionUpperSnake,+        Coders.caseConventionsDirectory = Util.CaseConventionLowerSnake,+        Coders.caseConventionsEnumValue = Util.CaseConventionLowerSnake,+        Coders.caseConventionsField = Util.CaseConventionLowerSnake,+        Coders.caseConventionsFile = Util.CaseConventionLowerSnake,+        Coders.caseConventionsModule = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTerm = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTermVariable = Util.CaseConventionLowerSnake,+        Coders.caseConventionsType = Util.CaseConventionLowerSnake,+        Coders.caseConventionsTypeVariable = Util.CaseConventionLowerSnake},+      Coders.languageDefaultFileExtension = (File.FileExtension "scm")}+  where+    literalVariants =+        Sets.fromList [+          Variants.LiteralVariantBinary,+          Variants.LiteralVariantBoolean,+          Variants.LiteralVariantDecimal,+          Variants.LiteralVariantFloat,+          Variants.LiteralVariantInteger,+          Variants.LiteralVariantString]+    floatTypes = Sets.fromList [+      Core.FloatTypeFloat64]+    integerTypes = Sets.fromList [+      Core.IntegerTypeBigint]+    termVariants =+        Sets.fromList [+          Variants.TermVariantAnnotated,+          Variants.TermVariantApplication,+          Variants.TermVariantEither,+          Variants.TermVariantCases,+          Variants.TermVariantLambda,+          Variants.TermVariantProject,+          Variants.TermVariantUnwrap,+          Variants.TermVariantTypeApplication,+          Variants.TermVariantTypeLambda,+          Variants.TermVariantLet,+          Variants.TermVariantList,+          Variants.TermVariantLiteral,+          Variants.TermVariantMap,+          Variants.TermVariantOptional,+          Variants.TermVariantPair,+          Variants.TermVariantRecord,+          Variants.TermVariantSet,+          Variants.TermVariantInject,+          Variants.TermVariantUnit,+          Variants.TermVariantVariable,+          Variants.TermVariantWrap]+    typeVariants =+        Sets.fromList [+          Variants.TypeVariantAnnotated,+          Variants.TypeVariantApplication,+          Variants.TypeVariantEither,+          Variants.TypeVariantEffect,+          Variants.TypeVariantFunction,+          Variants.TypeVariantForall,+          Variants.TypeVariantList,+          Variants.TypeVariantLiteral,+          Variants.TypeVariantMap,+          Variants.TypeVariantOptional,+          Variants.TypeVariantPair,+          Variants.TypeVariantRecord,+          Variants.TypeVariantSet,+          Variants.TypeVariantUnion,+          Variants.TypeVariantUnit,+          Variants.TypeVariantVariable,+          Variants.TypeVariantVoid,+          Variants.TypeVariantWrap]+    typePredicate = \_ -> True
src/main/haskell/Hydra/Lisp/Serde.hs view
@@ -23,7 +23,9 @@ import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic+import qualified Hydra.Overlay.Haskell.Lib.Math as Math import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals+import qualified Hydra.Overlay.Haskell.Lib.Ordering as Ordering import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings import qualified Hydra.Lisp.Syntax as Syntax@@ -185,6 +187,26 @@         name,         value])) +-- | Decode a canonical decimal digit string into a ((sign, digits), scale) nested pair+decimalDigitsAndScale :: String -> ((String, String), Int)+decimalDigitsAndScale s =++      let eParts = Strings.splitOn "e" s+          mantissa = Optionals.withDefault "" (Lists.head eParts)+          expText = Optionals.withDefault "" (Lists.head (Lists.drop 1 eParts))+          expTextUnplussed =+                  Logic.ifElse (Equality.equal (Optionals.withDefault 0 (Strings.charAt 0 expText)) 43) (Strings.fromList (Lists.drop 1 (Strings.toList expText))) expText+          expPart = Optionals.withDefault 0 (Literals.parseInt32 expTextUnplussed)+          isNeg = Equality.equal (Optionals.withDefault 0 (Strings.charAt 0 mantissa)) 45+          unsigned = Logic.ifElse isNeg (Strings.fromList (Lists.drop 1 (Strings.toList mantissa))) mantissa+          dotParts = Strings.splitOn "." unsigned+          intPart = Optionals.withDefault "" (Lists.head dotParts)+          fracPart = Optionals.withDefault "" (Lists.head (Lists.drop 1 dotParts))+          rawDigits = Strings.concat2 intPart fracPart+          rawScale = Math.sub (Strings.length fracPart) expPart+          sign = Logic.ifElse isNeg "-" ""+      in (Logic.ifElse (Ordering.lt rawScale 0) ((sign, (Strings.concat2 rawDigits (Strings.fromList (Lists.replicate (Math.negate rawScale) 48)))), 0) ((sign, rawDigits), rawScale))+ -- | The keyword for variable definitions defKeyword :: Syntax.Dialect -> String defKeyword d =@@ -657,6 +679,44 @@     case lit of       Syntax.LiteralInteger v0 -> Serialization.cst (Literals.printBigint (Syntax.integerLiteralValue v0))       Syntax.LiteralFloat v0 -> Serialization.cst (formatLispFloat d (Syntax.floatLiteralValue v0))+      Syntax.LiteralDecimal v0 ->+        let digits = Syntax.decimalLiteralDigits v0+        in case d of+          Syntax.DialectClojure -> Serialization.cst (Strings.concat2 digits "M")+          Syntax.DialectCommonLisp ->+            let parts = decimalDigitsAndScale digits+                signDigits = Pairs.first parts+                scale = Pairs.second parts+                coefficientText = Strings.concat2 (Pairs.first signDigits) (Pairs.second signDigits)+            in (Serialization.cst (Strings.concat [+              "'(",+              coefficientText,+              " . ",+              (Literals.printInt32 scale),+              ")"]))+          Syntax.DialectEmacsLisp ->+            let parts = decimalDigitsAndScale digits+                signDigits = Pairs.first parts+                scale = Pairs.second parts+                coefficientText = Strings.concat2 (Pairs.first signDigits) (Pairs.second signDigits)+            in (Serialization.cst (Strings.concat [+              "'(",+              coefficientText,+              " . ",+              (Literals.printInt32 scale),+              ")"]))+          Syntax.DialectScheme ->+            let parts = decimalDigitsAndScale digits+                signDigits = Pairs.first parts+                scale = Pairs.second parts+                coefficientText = Strings.concat2 (Pairs.first signDigits) (Pairs.second signDigits)+            in (Serialization.cst (Strings.concat [+              "'(",+              coefficientText,+              " . ",+              (Literals.printInt32 scale),+              ")"]))+          _ -> Serialization.cst (Strings.concat2 digits "M")       Syntax.LiteralString v0 ->         let e1 = Strings.join "\\\\" (Strings.splitOn "\\" v0)         in case d of
src/main/haskell/Hydra/Lisp/Syntax.hs view
@@ -215,6 +215,17 @@  _ConstructorPattern_arguments = Core.Name "arguments" +-- | An arbitrary-precision, scale-preserving decimal literal, pre-rendered as a plain (non-scientific) decimal digit string with the exact scale to preserve (e.g. "1.10", not "1.1"). Serializes as 1.10M in Clojure.+data DecimalLiteral =+  DecimalLiteral {+    -- | The decimal value as a plain (non-scientific) digit string, e.g. "1.10" or "-0.5"+    decimalLiteralDigits :: String}+  deriving (Eq, Ord, Read, Show)++_DecimalLiteral = Core.Name "hydra.lisp.syntax.DecimalLiteral"++_DecimalLiteral_digits = Core.Name "digits"+ -- | A destructuring binding in a let expression data DestructuringBinding =   DestructuringBinding {@@ -679,6 +690,8 @@   LiteralInteger IntegerLiteral |   -- | A floating-point literal   LiteralFloat FloatLiteral |+  -- | An arbitrary-precision, scale-preserving decimal literal (java.math.BigDecimal in Clojure, e.g. 1.10M). Dialects without a native decimal type have no use for this variant.+  LiteralDecimal DecimalLiteral |   -- | A string literal   LiteralString String |   -- | A character literal@@ -698,6 +711,8 @@ _Literal_integer = Core.Name "integer"  _Literal_float = Core.Name "float"++_Literal_decimal = Core.Name "decimal"  _Literal_string = Core.Name "string"