This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

push full worktree

+2883 -131
+17 -3
Main.lean
··· 18 18 | _ => judgment 19 19 | _ => judgment 20 20 21 + def renderValueForJudgment (value : Value) (judgment : Judgment) : String := 22 + match judgment.ty, value with 23 + | .decimal, .number (.exact q) => renderDecimal q 24 + | .int, .number (.exact q) => 25 + if q.den = 1 then toString q.num else renderValue value 26 + | _, _ => renderValue value 27 + 28 + def renderNumericStability (value : Value) (judgment : Judgment) : String := 29 + match judgment.ty with 30 + | .number => 31 + s!" [rational={rationalStabilityOfValue value}, decimal={decimalStabilityOfValue value}]" 32 + | _ => "" 33 + 21 34 def renderResult (value : Value) (judgment : Judgment) : String := 22 - s!"{renderValue value} : {renderJudgment (refineJudgmentFromValue value judgment)}" 35 + let refined := refineJudgmentFromValue value judgment 36 + s!"{renderValueForJudgment value refined} : {renderJudgment refined}{renderNumericStability value refined}" 23 37 24 38 unsafe def checkExprsWith (tyEnv : TyEnv) (env : Env) (exprs : List Expr) : IO (Except String (List (Value × Judgment))) := do 25 39 let rec loop (pending : List Expr) (acc : List (Value × Judgment)) : IO (Except String (List (Value × Judgment))) := do ··· 28 42 | expr :: rest => 29 43 match inferType tyEnv expr with 30 44 | .error err => 31 - pure (.error s!"type error: {reprStr err}") 45 + pure (.error s!"type error: {renderTypeError err}") 32 46 | .ok judgment => 33 47 match (← (eval env expr).toIO') with 34 48 | .ok value => ··· 86 100 | .bind name value => 87 101 match inferType tyEnv value with 88 102 | .error err => 89 - IO.eprintln s!"type error: {reprStr err}" 103 + IO.eprintln s!"type error: {renderTypeError err}" 90 104 repl tyEnv env 91 105 | .ok judgment => 92 106 match (← (eval env value).toIO') with
+1
Mlang/Http.lean
··· 1 1 namespace Mlang.Http 2 2 3 3 @[extern "mlang_http_get"] opaque httpGet (url : @& String) : IO String 4 + @[extern "mlang_aturi_parse_string"] opaque parseAturi (source : @& String) : IO String 4 5 5 6 end Mlang.Http
+945 -84
Mlang/Interpreter.lean
··· 7 7 open Nickel 8 8 9 9 abbrev Name := String 10 + structure Rational where 11 + num : Int 12 + den : Nat 13 + deriving Repr, Inhabited, BEq 14 + 15 + abbrev Decimal := Rational 16 + 17 + mutual 18 + inductive Generator where 19 + | exactRatio : Rational → Generator 20 + | exactDecimal : Decimal → Generator 21 + | rationalRefiner : LazyReal → Generator 22 + | decimalRefiner : LazyReal → Generator 23 + | piChudnovsky : Generator 24 + | sqrt : Decimal → Generator 25 + | add : Generator → Generator → Generator 26 + | sub : Generator → Generator → Generator 27 + | mul : Generator → Generator → Generator 28 + | div : Generator → Generator → Generator 29 + deriving Repr, Inhabited, BEq 30 + 31 + inductive LazyReal where 32 + | exact : Decimal → LazyReal 33 + | ratioProcess : Rational → LazyReal 34 + | decimalProcess : Decimal → LazyReal 35 + | pi : LazyReal 36 + | sqrt : Decimal → LazyReal 37 + | add : LazyReal → LazyReal → LazyReal 38 + | sub : LazyReal → LazyReal → LazyReal 39 + | mul : LazyReal → LazyReal → LazyReal 40 + | div : LazyReal → LazyReal → LazyReal 41 + | generated : Generator → LazyReal 42 + deriving Repr, Inhabited, BEq 43 + end 44 + 45 + def normalizeDecimalParts (negative : Bool) (whole frac : String) : String := 46 + let wholeChars := whole.toList.dropWhile (· = '0') 47 + let whole' := if wholeChars.isEmpty then "0" else String.ofList wholeChars 48 + let fracChars := frac.toList.reverse.dropWhile (· = '0') |>.reverse 49 + let frac' := if fracChars.isEmpty then "0" else String.ofList fracChars 50 + let sign := if negative && !(whole' = "0" && frac' = "0") then "-" else "" 51 + sign ++ whole' ++ "." ++ frac' 52 + 53 + def parseDecimalParts (repr : String) : Bool × String × String := 54 + let chars := repr.toList 55 + let (negative, chars) := 56 + match chars with 57 + | '-' :: rest => (true, rest) 58 + | _ => (false, chars) 59 + let rec split (acc : List Char) : List Char → List Char × List Char 60 + | [] => (acc.reverse, []) 61 + | '.' :: rest => (acc.reverse, rest) 62 + | c :: rest => split (c :: acc) rest 63 + let (wholeChars, fracChars) := split [] chars 64 + (negative, String.ofList wholeChars, String.ofList fracChars) 65 + 66 + def pow10 : Nat → Int 67 + | 0 => 1 68 + | n + 1 => 10 * pow10 n 69 + 70 + def powNat (base : Nat) : Nat → Nat 71 + | 0 => 1 72 + | n + 1 => base * powNat base n 73 + 74 + def mkRational (num : Int) (den : Nat) : Rational := 75 + if den = 0 then 76 + { num := 0, den := 1 } 77 + else if num = 0 then 78 + { num := 0, den := 1 } 79 + else 80 + let g := Nat.gcd num.natAbs den 81 + { num := num / Int.ofNat g, den := den / g } 82 + 83 + def parseDecimal (repr : String) : Decimal := 84 + let (negative, whole, frac) := parseDecimalParts repr 85 + let digits := whole ++ frac 86 + let magnitude := String.toInt? digits |>.getD 0 87 + let signed := if negative then -magnitude else magnitude 88 + mkRational signed (powNat 10 frac.length) 89 + 90 + def renderDecimalScaled (scaled : Int) (scale : Nat) : String := 91 + let negative := scaled < 0 92 + let mag := scaled.natAbs 93 + let digits := toString mag 94 + if scale = 0 then 95 + normalizeDecimalParts negative digits "0" 96 + else if digits.length <= scale then 97 + let zeros := String.ofList (List.replicate (scale - digits.length + 1) '0') 98 + let padded := zeros ++ digits 99 + let wholeLen := padded.length - scale 100 + normalizeDecimalParts negative (padded.take wholeLen |>.toString) (padded.drop wholeLen |>.toString) 101 + else 102 + let wholeLen := digits.length - scale 103 + normalizeDecimalParts negative (digits.take wholeLen |>.toString) (digits.drop wholeLen |>.toString) 104 + 105 + def decimalOfInt (n : Int) : Decimal := 106 + mkRational n 1 107 + 108 + def addDecimals (lhs rhs : Decimal) : Decimal := 109 + mkRational (lhs.num * Int.ofNat rhs.den + rhs.num * Int.ofNat lhs.den) (lhs.den * rhs.den) 110 + 111 + def subDecimals (lhs rhs : Decimal) : Decimal := 112 + mkRational (lhs.num * Int.ofNat rhs.den - rhs.num * Int.ofNat lhs.den) (lhs.den * rhs.den) 113 + 114 + def mulDecimals (lhs rhs : Decimal) : Decimal := 115 + mkRational (lhs.num * rhs.num) (lhs.den * rhs.den) 116 + 117 + def rationalEq (lhs rhs : Decimal) : Bool := 118 + lhs.num == rhs.num && lhs.den == rhs.den 119 + 120 + partial def countFactor (factor : Nat) (n : Nat) : Nat := 121 + let rec loop (count current : Nat) := 122 + if current = 0 then count 123 + else if current % factor = 0 then loop (count + 1) (current / factor) 124 + else count 125 + loop 0 n 126 + 127 + partial def stripFactor (factor : Nat) (n : Nat) : Nat := 128 + let rec loop (current : Nat) := 129 + if current = 0 then 0 130 + else if current % factor = 0 then loop (current / factor) 131 + else current 132 + loop n 133 + 134 + def renderDecimal (d : Decimal) : String := 135 + if d.den = 1 then 136 + renderDecimalScaled d.num 0 137 + else 138 + let twos := countFactor 2 d.den 139 + let withoutTwos := stripFactor 2 d.den 140 + let fives := countFactor 5 withoutTwos 141 + let rest := stripFactor 5 withoutTwos 142 + if rest = 1 then 143 + let scale := max twos fives 144 + let mult2 := powNat 2 (scale - twos) 145 + let mult5 := powNat 5 (scale - fives) 146 + let scaledNum := d.num * Int.ofNat (mult2 * mult5) 147 + renderDecimalScaled scaledNum scale 148 + else 149 + s!"{d.num}/{d.den}" 150 + 151 + def isTerminatingDecimal (q : Rational) : Bool := 152 + if q.den = 1 then 153 + true 154 + else 155 + let withoutTwos := stripFactor 2 q.den 156 + let withoutFives := stripFactor 5 withoutTwos 157 + withoutFives = 1 10 158 11 159 inductive Effect where 12 160 | error : Effect ··· 36 184 "{" ++ String.intercalate ", " names ++ "}" 37 185 38 186 inductive Ty where 187 + | number : Ty 39 188 | int : Ty 189 + | decimal : Ty 190 + | rational : Ty 191 + | lazyReal : Ty 192 + | stability : Ty 40 193 | bool : Ty 41 194 | string : Ty 42 195 | data : Ty 43 196 | dataInt : Ty 197 + | dataDecimal : Ty 198 + | dataRational : Ty 44 199 | dataBool : Ty 45 200 | dataString : Ty 46 201 | dataNull : Ty ··· 56 211 | null : Data 57 212 | bool : Bool → Data 58 213 | int : Int → Data 214 + | decimal : Decimal → Data 59 215 | string : String → Data 60 216 | array : List Data → Data 61 217 | record : List (String × Data) → Data ··· 63 219 64 220 inductive Expr where 65 221 | int : Int → Expr 222 + | decimal : Decimal → Expr 66 223 | bool : Bool → Expr 67 224 | string : String → Expr 68 225 | null : Expr ··· 81 238 | lam : Name → Ty → Expr → Expr 82 239 | app : Expr → Expr → Expr 83 240 deriving Repr, Inhabited 241 + 242 + inductive Numeric where 243 + | exact : Rational → Numeric 244 + | composite : LazyReal → Numeric 245 + deriving Repr, Inhabited, BEq 84 246 85 247 inductive Value where 86 - | int : Int → Value 248 + | number : Numeric → Value 249 + | stability : String → Value 87 250 | bool : Bool → Value 88 251 | string : String → Value 89 252 | data : Data → Value ··· 96 259 | builtinReadFileNickel : Value 97 260 | builtinParseNickel : Value 98 261 | builtinParseJson : Value 262 + | builtinGetAturi : Value 99 263 | builtinDataGet : Value 100 - | builtinDataGetField : Data → Value 264 + | builtinDataGetField : Value → Value 101 265 | builtinDataAt : Value 102 - | builtinDataAtIndex : Data → Value 266 + | builtinDataAtIndex : Value → Value 103 267 | builtinDataAsInt : Value 268 + | builtinDataAsDecimal : Value 269 + | builtinRationalToInt : Value 270 + | builtinRationalToDecimal : Value 104 271 | builtinDataAsString : Value 105 272 | builtinDataAsBool : Value 106 273 | builtinDataToJson : Value 107 274 | builtinDataToNickel : Value 275 + | builtinSqrt : Value 276 + | builtinProcess : Value 277 + | builtinSynthesize : Value 278 + | builtinFormula : Value 279 + | builtinApprox : Value 280 + | builtinApproxStep : Value → Value 281 + | builtinStabilize : Value 282 + | builtinStabilizeStep : Value → Value 283 + | builtinBounds : Value 284 + | builtinBoundsStep : Value → Value 285 + | builtinRationalStability : Value 286 + | builtinDecimalStability : Value 108 287 | closure : Name → Expr → List (Name × Value) → Value 109 288 deriving Repr, Inhabited 110 289 111 290 abbrev Env := List (Name × Value) 112 291 292 + inductive Observation where 293 + | asRational : Observation 294 + | asDecimal : Observation 295 + | asInt : Observation 296 + | rationalStability : Observation 297 + | decimalStability : Observation 298 + | getField : String → Observation 299 + | atIndex : Nat → Observation 300 + | approx : Nat → Observation 301 + | bounds : Nat → Observation 302 + deriving Repr, Inhabited 303 + 304 + inductive ObservationResult where 305 + | rational : Rational → ObservationResult 306 + | decimal : Decimal → ObservationResult 307 + | int : Int → ObservationResult 308 + | stability : String → ObservationResult 309 + | data : Data → ObservationResult 310 + | bounds : Decimal → Decimal → ObservationResult 311 + deriving Repr, Inhabited 312 + 113 313 inductive RuntimeError where 114 314 | unboundVariable : Name → RuntimeError 115 315 | typeError : String → RuntimeError ··· 119 319 120 320 abbrev EvalM := EIO RuntimeError 121 321 322 + def numericOfInt (n : Int) : Numeric := 323 + .exact (decimalOfInt n) 324 + 325 + def numericOfDecimal (d : Decimal) : Numeric := 326 + .exact d 327 + 328 + def valueToDecimal : Value → EvalM Decimal 329 + | .number (.exact q) => pure q 330 + | _ => throw (.typeError "expected a numeric value") 331 + 332 + def divDecimals (lhs rhs : Decimal) : EvalM Decimal := do 333 + if rhs.num = 0 then 334 + throw .divisionByZero 335 + else 336 + pure (mkRational (lhs.num * Int.ofNat rhs.den) (lhs.den * rhs.num.natAbs) |> 337 + fun q => if rhs.num < 0 then { q with num := -q.num } else q) 338 + 339 + def valueToLazyReal : Value → EvalM LazyReal 340 + | .number (.composite r) => pure r 341 + | .number (.exact q) => pure (.exact q) 342 + | _ => throw (.typeError "expected a numeric or LazyReal value") 343 + 344 + def generatorComplexity : Generator → Nat 345 + | .exactRatio _ => 1 346 + | .exactDecimal _ => 1 347 + | .rationalRefiner _ => 2 348 + | .decimalRefiner _ => 2 349 + | .piChudnovsky => 3 350 + | .sqrt _ => 2 351 + | .add lhs rhs => 1 + generatorComplexity lhs + generatorComplexity rhs 352 + | .sub lhs rhs => 1 + generatorComplexity lhs + generatorComplexity rhs 353 + | .mul lhs rhs => 1 + generatorComplexity lhs + generatorComplexity rhs 354 + | .div lhs rhs => 1 + generatorComplexity lhs + generatorComplexity rhs 355 + 356 + def selectFirstGoodEnough [Inhabited α] (candidates : List α) (goodEnough : α → Bool) : α := 357 + match candidates.find? goodEnough with 358 + | some candidate => candidate 359 + | none => 360 + match candidates with 361 + | candidate :: _ => candidate 362 + | [] => default 363 + 364 + def generatorGoodEnough : Generator → Bool 365 + | .exactRatio _ => true 366 + | .exactDecimal _ => true 367 + | .rationalRefiner _ => true 368 + | .decimalRefiner _ => true 369 + | .piChudnovsky => true 370 + | .sqrt _ => true 371 + | .add lhs rhs => generatorGoodEnough lhs && generatorGoodEnough rhs 372 + | .sub lhs rhs => generatorGoodEnough lhs && generatorGoodEnough rhs 373 + | .mul lhs rhs => generatorGoodEnough lhs && generatorGoodEnough rhs 374 + | .div lhs rhs => generatorGoodEnough lhs && generatorGoodEnough rhs 375 + 376 + partial def synthesizedCandidates (r : LazyReal) : List Generator := 377 + match r with 378 + | .exact q => 379 + if isTerminatingDecimal q then 380 + [.exactDecimal q, .exactRatio q] 381 + else 382 + [.exactRatio q, .decimalRefiner (.exact q)] 383 + | .ratioProcess q => 384 + if isTerminatingDecimal q then 385 + [.exactDecimal q, .exactRatio q] 386 + else 387 + [.exactRatio q, .decimalRefiner (.ratioProcess q)] 388 + | .decimalProcess d => 389 + [.exactDecimal d, .exactRatio d] 390 + | .generated g => 391 + [g, .decimalRefiner (.generated g), .rationalRefiner (.generated g)] 392 + | .pi => 393 + [.decimalRefiner .pi, .rationalRefiner .pi, .piChudnovsky] 394 + | .sqrt d => 395 + [.decimalRefiner (.sqrt d), .rationalRefiner (.sqrt d), .sqrt d] 396 + | .add lhs rhs => 397 + let lhsGen := selectFirstGoodEnough (synthesizedCandidates lhs) generatorGoodEnough 398 + let rhsGen := selectFirstGoodEnough (synthesizedCandidates rhs) generatorGoodEnough 399 + [.add lhsGen rhsGen, .decimalRefiner (.add lhs rhs), .rationalRefiner (.add lhs rhs)] 400 + | .sub lhs rhs => 401 + let lhsGen := selectFirstGoodEnough (synthesizedCandidates lhs) generatorGoodEnough 402 + let rhsGen := selectFirstGoodEnough (synthesizedCandidates rhs) generatorGoodEnough 403 + [.sub lhsGen rhsGen, .decimalRefiner (.sub lhs rhs), .rationalRefiner (.sub lhs rhs)] 404 + | .mul lhs rhs => 405 + let lhsGen := selectFirstGoodEnough (synthesizedCandidates lhs) generatorGoodEnough 406 + let rhsGen := selectFirstGoodEnough (synthesizedCandidates rhs) generatorGoodEnough 407 + [.mul lhsGen rhsGen, .decimalRefiner (.mul lhs rhs), .rationalRefiner (.mul lhs rhs)] 408 + | .div lhs rhs => 409 + let lhsGen := selectFirstGoodEnough (synthesizedCandidates lhs) generatorGoodEnough 410 + let rhsGen := selectFirstGoodEnough (synthesizedCandidates rhs) generatorGoodEnough 411 + [.div lhsGen rhsGen, .decimalRefiner (.div lhs rhs), .rationalRefiner (.div lhs rhs)] 412 + 413 + def chooseSynthesizedGenerator (r : LazyReal) : Generator := 414 + selectFirstGoodEnough (synthesizedCandidates r) generatorGoodEnough 415 + 416 + mutual 417 + partial def renderGeneratorFormula : Generator → String 418 + | .exactRatio q => s!"{q.num}/{q.den}" 419 + | .exactDecimal d => renderDecimal d 420 + | .rationalRefiner r => s!"rationalRefine({renderLazyFormula r})" 421 + | .decimalRefiner r => s!"decimalRefine({renderLazyFormula r})" 422 + | .piChudnovsky => 423 + "426880 * sqrt(10005) / sum(k => ((-1)^k * (6k)! * (13591409 + 545140134k)) / ((3k)! * (k!)^3 * 640320^(3k)), k = 0..inf)" 424 + | .sqrt d => s!"sqrt({renderDecimal d})" 425 + | .add lhs rhs => s!"({renderGeneratorFormula lhs}) + ({renderGeneratorFormula rhs})" 426 + | .sub lhs rhs => s!"({renderGeneratorFormula lhs}) - ({renderGeneratorFormula rhs})" 427 + | .mul lhs rhs => s!"({renderGeneratorFormula lhs}) * ({renderGeneratorFormula rhs})" 428 + | .div lhs rhs => s!"({renderGeneratorFormula lhs}) / ({renderGeneratorFormula rhs})" 429 + 430 + partial def renderLazyFormula : LazyReal → String 431 + | .exact q => renderDecimal q 432 + | .ratioProcess q => s!"ratio({q.num}/{q.den})" 433 + | .decimalProcess d => s!"decimal({renderDecimal d})" 434 + | .pi => "pi" 435 + | .sqrt d => s!"sqrt({renderDecimal d})" 436 + | .add lhs rhs => s!"({renderLazyFormula lhs}) + ({renderLazyFormula rhs})" 437 + | .sub lhs rhs => s!"({renderLazyFormula lhs}) - ({renderLazyFormula rhs})" 438 + | .mul lhs rhs => s!"({renderLazyFormula lhs}) * ({renderLazyFormula rhs})" 439 + | .div lhs rhs => s!"({renderLazyFormula lhs}) / ({renderLazyFormula rhs})" 440 + | .generated g => renderGeneratorFormula g 441 + end 442 + 443 + def formulaOfValue (value : Value) : EvalM String := do 444 + match value with 445 + | .number (.exact q) => 446 + pure (renderGeneratorFormula (chooseSynthesizedGenerator (.exact q))) 447 + | .number (.composite r) => 448 + pure (renderGeneratorFormula (chooseSynthesizedGenerator r)) 449 + | _ => 450 + let q ← valueToDecimal value 451 + pure (renderGeneratorFormula (chooseSynthesizedGenerator (.exact q))) 452 + 453 + def synthesizeNumeric (value : Value) : EvalM Numeric := do 454 + match value with 455 + | .number (.exact q) => 456 + pure (.composite (.generated (chooseSynthesizedGenerator (.exact q)))) 457 + | .number (.composite r) => 458 + pure (.composite (.generated (chooseSynthesizedGenerator r))) 459 + | _ => 460 + let q ← valueToDecimal value 461 + pure (.composite (.generated (chooseSynthesizedGenerator (.exact q)))) 462 + 463 + partial def natSqrtSearch (target lo hi : Nat) : Nat := 464 + if lo + 1 >= hi then 465 + lo 466 + else 467 + let mid := lo + (hi - lo) / 2 468 + if mid * mid ≤ target then 469 + natSqrtSearch target mid hi 470 + else 471 + natSqrtSearch target lo mid 472 + 473 + def natSqrtFloor (target : Nat) : Nat := 474 + natSqrtSearch target 0 (target + 1) 475 + 476 + def sqrtBoundsOfDecimal (d : Decimal) (steps : Nat) : EvalM (Decimal × Decimal) := do 477 + if d.num < 0 then 478 + throw (.typeError "sqrt expects a non-negative decimal") 479 + else 480 + let scale := steps 481 + let scaledTarget := d.num.natAbs * powNat 10 (2 * scale) / d.den 482 + let loNat := natSqrtFloor scaledTarget 483 + let lo := mkRational (Int.ofNat loNat) (powNat 10 scale) 484 + let step := mkRational 1 (powNat 10 scale) 485 + pure (lo, addDecimals lo step) 486 + 487 + def natFactorial : Nat → Nat 488 + | 0 => 1 489 + | n + 1 => (n + 1) * natFactorial n 490 + 491 + def chudnovskyTermMag (k : Nat) : Decimal := 492 + let sixFact := natFactorial (6 * k) 493 + let threeFact := natFactorial (3 * k) 494 + let kFact := natFactorial k 495 + let coeff : Int := 13591409 + 545140134 * Int.ofNat k 496 + let num := Int.ofNat sixFact * coeff 497 + let den := threeFact * kFact * kFact * kFact * powNat 640320 (3 * k) 498 + mkRational num den 499 + 500 + def chudnovskySignedTerm (k : Nat) : Decimal := 501 + let mag := chudnovskyTermMag k 502 + if k % 2 = 0 then mag else { mag with num := -mag.num } 503 + 504 + def chudnovskySum (terms : Nat) : Decimal := 505 + let rec loop (k : Nat) (acc : Decimal) := 506 + if k < terms then 507 + loop (k + 1) (addDecimals acc (chudnovskySignedTerm k)) 508 + else 509 + acc 510 + loop 0 (decimalOfInt 0) 511 + 512 + def piBounds (steps : Nat) : EvalM (Decimal × Decimal) := do 513 + let terms := steps / 14 + 1 514 + let sum := chudnovskySum terms 515 + let tail := chudnovskyTermMag terms 516 + let sumLo := subDecimals sum tail 517 + let sumHi := addDecimals sum tail 518 + let (sqrtLo, sqrtHi) ← sqrtBoundsOfDecimal (decimalOfInt 10005) (steps + 2) 519 + let coeff := decimalOfInt 426880 520 + let cLo := mulDecimals coeff sqrtLo 521 + let cHi := mulDecimals coeff sqrtHi 522 + let lo ← divDecimals cLo sumHi 523 + let hi ← divDecimals cHi sumLo 524 + pure (lo, hi) 525 + 526 + def minDecimal (a b : Decimal) : Decimal := 527 + if a.num * Int.ofNat b.den <= b.num * Int.ofNat a.den then a else b 528 + 529 + def maxDecimal (a b : Decimal) : Decimal := 530 + if a.num * Int.ofNat b.den >= b.num * Int.ofNat a.den then a else b 531 + 532 + def roundRationalToScale (q : Rational) (scale : Nat) : Rational := 533 + let factor := powNat 10 scale 534 + let scaledNum := q.num * Int.ofNat factor 535 + let denInt := Int.ofNat q.den 536 + let adjust := Int.ofNat (q.den / 2) 537 + let rounded := 538 + if scaledNum < 0 then 539 + (scaledNum - adjust) / denInt 540 + else 541 + (scaledNum + adjust) / denInt 542 + mkRational rounded factor 543 + 544 + def mulBounds (lo1 hi1 lo2 hi2 : Decimal) : Decimal × Decimal := 545 + let p1 := mulDecimals lo1 lo2 546 + let p2 := mulDecimals lo1 hi2 547 + let p3 := mulDecimals hi1 lo2 548 + let p4 := mulDecimals hi1 hi2 549 + let lo := minDecimal (minDecimal p1 p2) (minDecimal p3 p4) 550 + let hi := maxDecimal (maxDecimal p1 p2) (maxDecimal p3 p4) 551 + (lo, hi) 552 + 553 + mutual 554 + partial def boundsGenerator (g : Generator) (steps : Nat) : EvalM (Decimal × Decimal) := do 555 + match g with 556 + | .exactRatio q => pure (q, q) 557 + | .exactDecimal d => pure (d, d) 558 + | .rationalRefiner r => 559 + let q ← approxLazyReal r steps 560 + pure (q, q) 561 + | .decimalRefiner r => 562 + let q ← approxLazyReal r steps 563 + pure (roundRationalToScale q steps, roundRationalToScale q steps) 564 + | .piChudnovsky => piBounds steps 565 + | .sqrt d => sqrtBoundsOfDecimal d steps 566 + | .add lhs rhs => 567 + let (llo, lhi) ← boundsGenerator lhs steps 568 + let (rlo, rhi) ← boundsGenerator rhs steps 569 + pure (addDecimals llo rlo, addDecimals lhi rhi) 570 + | .sub lhs rhs => 571 + let (llo, lhi) ← boundsGenerator lhs steps 572 + let (rlo, rhi) ← boundsGenerator rhs steps 573 + pure (subDecimals llo rhi, subDecimals lhi rlo) 574 + | .mul lhs rhs => 575 + let (llo, lhi) ← boundsGenerator lhs steps 576 + let (rlo, rhi) ← boundsGenerator rhs steps 577 + pure (mulBounds llo lhi rlo rhi) 578 + | .div lhs rhs => 579 + let (llo, lhi) ← boundsGenerator lhs steps 580 + let (rlo, rhi) ← boundsGenerator rhs steps 581 + if rlo.num <= 0 && 0 <= rhi.num then 582 + throw (.typeError "generated division interval crosses zero") 583 + else 584 + let invLo ← divDecimals (decimalOfInt 1) rhi 585 + let invHi ← divDecimals (decimalOfInt 1) rlo 586 + pure (mulBounds llo lhi invLo invHi) 587 + 588 + partial def approxGenerator (g : Generator) (steps : Nat) : EvalM Decimal := do 589 + match g with 590 + | .exactRatio q => pure q 591 + | .exactDecimal d => pure d 592 + | .rationalRefiner r => approxLazyReal r steps 593 + | .decimalRefiner r => 594 + let q ← approxLazyReal r steps 595 + pure (roundRationalToScale q steps) 596 + | .piChudnovsky => 597 + let (lo, hi) ← piBounds steps 598 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 599 + | .sqrt d => 600 + let (lo, hi) ← sqrtBoundsOfDecimal d steps 601 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 602 + | .add _ _ | .sub _ _ | .mul _ _ | .div _ _ => 603 + let (lo, hi) ← boundsGenerator g steps 604 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 605 + 606 + partial def boundsLazyReal (r : LazyReal) (steps : Nat) : EvalM (Decimal × Decimal) := do 607 + match r with 608 + | .exact d => pure (d, d) 609 + | .ratioProcess q => pure (q, q) 610 + | .decimalProcess d => pure (d, d) 611 + | .generated g => boundsGenerator g steps 612 + | .pi => piBounds steps 613 + | .sqrt d => sqrtBoundsOfDecimal d steps 614 + | .add lhs rhs => 615 + let (llo, lhi) ← boundsLazyReal lhs steps 616 + let (rlo, rhi) ← boundsLazyReal rhs steps 617 + pure (addDecimals llo rlo, addDecimals lhi rhi) 618 + | .sub lhs rhs => 619 + let (llo, lhi) ← boundsLazyReal lhs steps 620 + let (rlo, rhi) ← boundsLazyReal rhs steps 621 + pure (subDecimals llo rhi, subDecimals lhi rlo) 622 + | .mul lhs rhs => 623 + let (llo, lhi) ← boundsLazyReal lhs steps 624 + let (rlo, rhi) ← boundsLazyReal rhs steps 625 + pure (mulBounds llo lhi rlo rhi) 626 + | .div lhs rhs => 627 + let (llo, lhi) ← boundsLazyReal lhs steps 628 + let (rlo, rhi) ← boundsLazyReal rhs steps 629 + if rlo.num <= 0 && 0 <= rhi.num then 630 + throw (.typeError "lazy division interval crosses zero") 631 + else 632 + let invLo ← divDecimals (decimalOfInt 1) rhi 633 + let invHi ← divDecimals (decimalOfInt 1) rlo 634 + pure (mulBounds llo lhi invLo invHi) 635 + 636 + partial def approxLazyReal (r : LazyReal) (steps : Nat) : EvalM Decimal := do 637 + match r with 638 + | .exact d => pure d 639 + | .ratioProcess q => pure q 640 + | .decimalProcess d => pure d 641 + | .generated g => approxGenerator g steps 642 + | .pi => 643 + let (lo, hi) ← piBounds steps 644 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 645 + | .sqrt d => 646 + let (lo, hi) ← sqrtBoundsOfDecimal d steps 647 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 648 + | .add _ _ | .sub _ _ | .mul _ _ | .div _ _ => 649 + let (lo, hi) ← boundsLazyReal r steps 650 + divDecimals (addDecimals lo hi) (decimalOfInt 2) 651 + end 652 + 653 + def stabilizeNumeric (value : Value) (steps : Nat) : EvalM Rational := do 654 + match value with 655 + | .number (.exact q) => pure (roundRationalToScale q steps) 656 + | .number (.composite r) => 657 + let q ← approxLazyReal r steps 658 + pure (roundRationalToScale q steps) 659 + | _ => 660 + let q ← valueToDecimal value 661 + pure (roundRationalToScale q steps) 662 + 122 663 def Env.lookup (env : Env) (name : Name) : Option Value := 123 664 match env with 124 665 | [] => none 125 666 | (n, v) :: rest => if n = name then some v else rest.lookup name 126 667 127 668 def expectInt : Value → EvalM Int 128 - | .int n => pure n 669 + | .number (.exact q) => 670 + if q.den = 1 then pure q.num else throw (.typeError "expected an integer") 129 671 | _ => throw (.typeError "expected an integer") 130 672 673 + def expectDecimal : Value → EvalM Decimal 674 + | .number (.exact q) => pure q 675 + | _ => throw (.typeError "expected a decimal") 676 + 677 + def expectLazyReal : Value → EvalM LazyReal 678 + | .number (.composite r) => pure r 679 + | _ => throw (.typeError "expected a LazyReal") 680 + 131 681 def expectBool : Value → EvalM Bool 132 682 | .bool b => pure b 133 683 | _ => throw (.typeError "expected a boolean") ··· 140 690 | .data term => pure term 141 691 | _ => throw (.typeError "expected a data value") 142 692 693 + def expectWholeNat (value : Value) : EvalM Nat := do 694 + let q ← valueToDecimal value 695 + if q.den ≠ 1 then 696 + throw (.typeError "expected a whole rational") 697 + else if q.num < 0 then 698 + throw (.typeError "expected a non-negative whole rational") 699 + else 700 + pure q.num.toNat 701 + 702 + def rationalStabilityOfValue (value : Value) : String := 703 + match value with 704 + | .number (.composite (.ratioProcess _)) => "Immediate" 705 + | .number (.composite (.decimalProcess _)) => "Immediate" 706 + | .number (.composite (.generated (.exactRatio _))) => "Immediate" 707 + | .number (.composite (.generated (.exactDecimal _))) => "Immediate" 708 + | .number (.exact _) => "Immediate" 709 + | .number (.composite _) => "Refining" 710 + | _ => "Unavailable" 711 + 712 + def decimalStabilityOfRational (q : Rational) : String := 713 + if isTerminatingDecimal q then "Terminating" else "Periodic" 714 + 715 + def decimalStabilityOfValue (value : Value) : String := 716 + match value with 717 + | .number (.composite (.ratioProcess q)) => decimalStabilityOfRational q 718 + | .number (.composite (.decimalProcess d)) => decimalStabilityOfRational d 719 + | .number (.composite (.generated (.exactRatio q))) => decimalStabilityOfRational q 720 + | .number (.composite (.generated (.exactDecimal d))) => decimalStabilityOfRational d 721 + | .number (.exact q) => decimalStabilityOfRational q 722 + | .number (.composite _) => "Refining" 723 + | _ => "Unavailable" 724 + 725 + def observeValue (value : Value) (obs : Observation) : EvalM ObservationResult := do 726 + match obs with 727 + | .asRational => 728 + match value with 729 + | .number (.exact q) => pure (.rational q) 730 + | .number (.composite _) => 731 + throw (.typeError s!"rational observation failed: number is {rationalStabilityOfValue value}, not Immediate") 732 + | _ => 733 + pure (.rational (← valueToDecimal value)) 734 + | .asDecimal => 735 + match value with 736 + | .number (.exact q) => 737 + if isTerminatingDecimal q then 738 + pure (.decimal q) 739 + else 740 + throw (.typeError s!"decimal observation failed: number is {decimalStabilityOfValue value}, not Terminating") 741 + | .number (.composite _) => 742 + throw (.typeError s!"decimal observation failed: number is {decimalStabilityOfValue value}, not Terminating") 743 + | _ => 744 + let q ← valueToDecimal value 745 + if isTerminatingDecimal q then 746 + pure (.decimal q) 747 + else 748 + throw (.typeError s!"decimal observation failed: number is {decimalStabilityOfValue value}, not Terminating") 749 + | .asInt => 750 + match value with 751 + | .number (.exact q) => 752 + if q.den = 1 then 753 + pure (.int q.num) 754 + else 755 + throw (.typeError "integer observation failed: number is not whole") 756 + | .number (.composite _) => 757 + throw (.typeError s!"integer observation failed: number is {rationalStabilityOfValue value}, not Immediate") 758 + | _ => 759 + let q ← valueToDecimal value 760 + if q.den = 1 then 761 + pure (.int q.num) 762 + else 763 + throw (.typeError "integer observation failed: number is not whole") 764 + | .rationalStability => 765 + pure (.stability (rationalStabilityOfValue value)) 766 + | .decimalStability => 767 + pure (.stability (decimalStabilityOfValue value)) 768 + | .getField key => 769 + match value with 770 + | .data (.record fields) => 771 + match fields.find? (fun (name, _) => name = key) with 772 + | some (_, field) => pure (.data field) 773 + | none => throw (.typeError s!"missing field: {key}") 774 + | _ => throw (.typeError "get expects a record") 775 + | .atIndex idx => 776 + let rec arrayGet? : List Data → Nat → Option Data 777 + | [], _ => none 778 + | x :: _, 0 => some x 779 + | _ :: xs, n + 1 => arrayGet? xs n 780 + match value with 781 + | .data (.array items) => 782 + match arrayGet? items idx with 783 + | some item => pure (.data item) 784 + | none => throw (RuntimeError.typeError s!"index out of bounds: {idx}") 785 + | _ => throw (RuntimeError.typeError "at expects an array") 786 + | .approx steps => 787 + let r ← valueToLazyReal value 788 + pure (.rational (← approxLazyReal r steps)) 789 + | .bounds steps => 790 + let r ← valueToLazyReal value 791 + let (lo, hi) ← boundsLazyReal r steps 792 + pure (.bounds lo hi) 793 + 143 794 def valueToData : Value → EvalM Data 144 795 | .data term => pure term 145 - | .int n => pure (.int n) 796 + | .number (.exact q) => pure (.decimal q) 146 797 | .bool b => pure (.bool b) 147 798 | .string s => pure (.string s) 148 - | _ => throw (.typeError "data literals only support Int, Bool, String, and Data values") 799 + | _ => throw (.typeError "data literals only support Int, Decimal, Bool, String, and Data values") 149 800 150 801 partial def dataType : Data → Ty 151 802 | .null => .dataNull 152 803 | .bool _ => .dataBool 153 804 | .int _ => .dataInt 805 + | .decimal _ => .dataRational 154 806 | .string _ => .dataString 155 807 | .array [] => .dataArray .data 156 808 | .array (x :: xs) => ··· 169 821 170 822 def liftScalarDataTy : Ty → Ty 171 823 | .dataInt => .int 824 + | .dataDecimal => .decimal 825 + | .dataRational => .rational 172 826 | .dataBool => .bool 173 827 | .dataString => .string 174 828 | ty => ty ··· 176 830 partial def refineKnownDataTy (ty : Ty) : Ty := 177 831 match ty with 178 832 | .dataInt => .int 833 + | .dataDecimal => .decimal 834 + | .dataRational => .rational 179 835 | .dataBool => .bool 180 836 | .dataString => .string 181 837 | .dataNull => .data ··· 205 861 | .null => .null 206 862 | .bool b => .bool b 207 863 | .int n => .int n 864 + | .decimal d => .decimal (parseDecimal d) 208 865 | .string s => .string s 209 866 | .array xs => .array (xs.map Data.ofNickel) 210 867 | .record fields => .record (fields.map (fun (k, v) => (k, Data.ofNickel v))) ··· 248 905 | .null => "null" 249 906 | .bool b => toString b 250 907 | .int n => toString n 908 + | .decimal d => renderDecimal d 251 909 | .string s => renderJsonString s 252 910 | .array xs => "[" ++ String.intercalate ", " (xs.map renderNickelData) ++ "]" 253 911 | .record fields => ··· 258 916 | .null => "null" 259 917 | .bool b => if b then "true" else "false" 260 918 | .int n => toString n 919 + | .decimal d => renderDecimal d 261 920 | .string s => renderJsonString s 262 921 | .array xs => "[" ++ String.intercalate ", " (xs.map renderJsonData) ++ "]" 263 922 | .record fields => ··· 271 930 | "readFileNickel" => some (.funTy .string [.error, .io] .data) 272 931 | "parseNickel" => some (.funTy .string [.error] .data) 273 932 | "parseJson" => some (.funTy .string [.error] .data) 933 + | "getAturi" => some (.funTy .string [.error, .io] .data) 274 934 | "get" => some (.funTy .data [] (.funTy .string [.error] .data)) 275 - | "at" => some (.funTy .data [] (.funTy .int [.error] .data)) 935 + | "at" => some (.funTy .data [] (.funTy .number [.error] .data)) 276 936 | "asInt" => some (.funTy .data [.error] .int) 937 + | "asDecimal" => some (.funTy .data [.error] .decimal) 938 + | "toInt" => some (.funTy .number [.error] .int) 939 + | "toDecimal" => some (.funTy .number [.error] .decimal) 277 940 | "asString" => some (.funTy .data [.error] .string) 278 941 | "asBool" => some (.funTy .data [.error] .bool) 279 942 | "toJson" => some (.funTy .data [] .string) 280 943 | "toNickel" => some (.funTy .data [] .string) 944 + | "rationalStability" => some (.funTy .number [] .stability) 945 + | "decimalStability" => some (.funTy .number [] .stability) 946 + | "pi" => some .number 947 + | "sqrt" => some (.funTy .number [.error] .number) 948 + | "process" => some (.funTy .number [] .number) 949 + | "synthesize" => some (.funTy .number [.error] .number) 950 + | "formula" => some (.funTy .number [.error] .string) 951 + | "lazyRationalStability" => some (.funTy .number [] .stability) 952 + | "lazyDecimalStability" => some (.funTy .number [] .stability) 953 + | "stabilize" => some (.funTy .number [] (.funTy .number [.error] .number)) 954 + | "approx" => some (.funTy .number [] (.funTy .number [.error] .number)) 955 + | "bounds" => some (.funTy .number [] (.funTy .number [.error] .data)) 281 956 | _ => none 282 957 283 958 def builtinValue? (name : Name) : Option Value := ··· 287 962 | "readFileNickel" => some .builtinReadFileNickel 288 963 | "parseNickel" => some .builtinParseNickel 289 964 | "parseJson" => some .builtinParseJson 965 + | "getAturi" => some .builtinGetAturi 290 966 | "get" => some .builtinDataGet 291 967 | "at" => some .builtinDataAt 292 968 | "asInt" => some .builtinDataAsInt 969 + | "asDecimal" => some .builtinDataAsDecimal 970 + | "toInt" => some .builtinRationalToInt 971 + | "toDecimal" => some .builtinRationalToDecimal 293 972 | "asString" => some .builtinDataAsString 294 973 | "asBool" => some .builtinDataAsBool 295 974 | "toJson" => some .builtinDataToJson 296 975 | "toNickel" => some .builtinDataToNickel 976 + | "rationalStability" => some .builtinRationalStability 977 + | "decimalStability" => some .builtinDecimalStability 978 + | "pi" => some (.number (.composite .pi)) 979 + | "sqrt" => some .builtinSqrt 980 + | "process" => some .builtinProcess 981 + | "synthesize" => some .builtinSynthesize 982 + | "formula" => some .builtinFormula 983 + | "lazyRationalStability" => some .builtinRationalStability 984 + | "lazyDecimalStability" => some .builtinDecimalStability 985 + | "stabilize" => some .builtinStabilize 986 + | "approx" => some .builtinApprox 987 + | "bounds" => some .builtinBounds 297 988 | _ => none 298 989 299 990 mutual ··· 321 1012 let source ← expectString argVal 322 1013 let rendered ← IO.toEIO (fun err => .ioError (toString err)) (NickelHost.evalJsonString source) 323 1014 pure (.data (← parseRenderedData rendered)) 324 - | .builtinDataGet => do 325 - let term ← expectData argVal 326 - pure (.builtinDataGetField term) 327 - | .builtinDataGetField term => do 1015 + | .builtinGetAturi => do 1016 + let source ← expectString argVal 1017 + let rendered ← IO.toEIO (fun err => .ioError (toString err)) (Http.parseAturi source) 1018 + pure (.data (← parseRenderedData rendered)) 1019 + | .builtinDataGet => pure (.builtinDataGetField argVal) 1020 + | .builtinDataGetField target => do 328 1021 let key ← expectString argVal 329 - match term with 330 - | .record fields => 331 - match fields.find? (fun (name, _) => name = key) with 332 - | some (_, value) => pure (.data value) 333 - | none => throw (.typeError s!"missing field: {key}") 334 - | _ => throw (.typeError "get expects a record") 335 - | .builtinDataAt => do 336 - let term ← expectData argVal 337 - pure (.builtinDataAtIndex term) 338 - | .builtinDataAtIndex term => do 339 - let idx ← expectInt argVal 340 - if idx < 0 then 341 - throw (.typeError s!"negative index: {idx}") 342 - else 343 - match term with 344 - | .array items => 345 - match dataArrayGet? items idx.toNat with 346 - | some value => pure (.data value) 347 - | none => throw (RuntimeError.typeError s!"index out of bounds: {idx}") 348 - | _ => throw (.typeError "at expects an array") 1022 + match (← observeValue target (.getField key)) with 1023 + | .data value => pure (.data value) 1024 + | _ => throw (.typeError "get observation returned non-data") 1025 + | .builtinDataAt => pure (.builtinDataAtIndex argVal) 1026 + | .builtinDataAtIndex target => do 1027 + let idx ← expectWholeNat argVal 1028 + match (← observeValue target (.atIndex idx)) with 1029 + | .data value => pure (.data value) 1030 + | _ => throw (.typeError "at observation returned non-data") 349 1031 | .builtinDataAsInt => do 350 1032 let term ← expectData argVal 351 1033 match term with 352 - | .int n => pure (.int n) 1034 + | .int n => pure (.number (numericOfInt n)) 353 1035 | _ => throw (.typeError "asInt expects an integer") 1036 + | .builtinDataAsDecimal => do 1037 + let term ← expectData argVal 1038 + match term with 1039 + | .decimal d => pure (.number (numericOfDecimal d)) 1040 + | _ => throw (.typeError "asDecimal expects a decimal") 1041 + | .builtinRationalToInt => do 1042 + match (← observeValue argVal .asInt) with 1043 + | .int n => pure (.number (numericOfInt n)) 1044 + | _ => throw (.typeError "toInt observation returned non-int") 1045 + | .builtinRationalToDecimal => do 1046 + match (← observeValue argVal .asDecimal) with 1047 + | .decimal d => pure (.number (numericOfDecimal d)) 1048 + | _ => throw (.typeError "toDecimal observation returned non-decimal") 354 1049 | .builtinDataAsString => do 355 1050 let term ← expectData argVal 356 1051 match term with ··· 367 1062 | .builtinDataToNickel => do 368 1063 let term ← expectData argVal 369 1064 pure (.string (renderNickelData term)) 1065 + | .builtinRationalStability => do 1066 + match (← observeValue argVal .rationalStability) with 1067 + | .stability label => pure (.stability label) 1068 + | _ => throw (.typeError "rationalStability observation returned non-stability") 1069 + | .builtinDecimalStability => do 1070 + match (← observeValue argVal .decimalStability) with 1071 + | .stability label => pure (.stability label) 1072 + | _ => throw (.typeError "decimalStability observation returned non-stability") 1073 + | .builtinSqrt => do 1074 + let d ← valueToDecimal argVal 1075 + if d.num < 0 then 1076 + throw (.typeError "sqrt expects a non-negative decimal") 1077 + else 1078 + pure (.number (.composite (.sqrt d))) 1079 + | .builtinProcess => do 1080 + match argVal with 1081 + | .number (.exact q) => pure (.number (.composite (.exact q))) 1082 + | .number (.composite r) => pure (.number (.composite r)) 1083 + | _ => throw (.typeError "process expects a number") 1084 + | .builtinSynthesize => do 1085 + pure (.number (← synthesizeNumeric argVal)) 1086 + | .builtinFormula => do 1087 + pure (.string (← formulaOfValue argVal)) 1088 + | .builtinStabilize => pure (.builtinStabilizeStep argVal) 1089 + | .builtinStabilizeStep target => do 1090 + let steps ← expectWholeNat argVal 1091 + pure (.number (.exact (← stabilizeNumeric target steps))) 1092 + | .builtinApprox => pure (.builtinApproxStep argVal) 1093 + | .builtinApproxStep target => do 1094 + let steps ← expectWholeNat argVal 1095 + match (← observeValue target (.approx steps)) with 1096 + | .rational q => pure (.number (.exact q)) 1097 + | _ => throw (.typeError "approx observation returned non-rational") 1098 + | .builtinBounds => pure (.builtinBoundsStep argVal) 1099 + | .builtinBoundsStep target => do 1100 + let steps ← expectWholeNat argVal 1101 + match (← observeValue target (.bounds steps)) with 1102 + | .bounds lo hi => pure (.data (.record [("lo", .decimal lo), ("hi", .decimal hi)])) 1103 + | _ => throw (.typeError "bounds observation returned non-bounds") 1104 + | .data (.record fields) => 1105 + let key ← expectString argVal 1106 + match fields.find? (fun (name, _) => name = key) with 1107 + | some (_, value) => pure (.data value) 1108 + | none => throw (.typeError s!"missing field: {key}") 1109 + | .data (.array items) => 1110 + let idx ← expectWholeNat argVal 1111 + match dataArrayGet? items idx with 1112 + | some value => pure (.data value) 1113 + | none => throw (RuntimeError.typeError s!"index out of bounds: {idx}") 1114 + | .data _ => 1115 + throw (.typeError "data value is not callable with this argument") 370 1116 | _ => 371 - match fnVal, argVal with 372 - | .data (.record fields), .string key => 373 - match fields.find? (fun (name, _) => name = key) with 374 - | some (_, value) => pure (.data value) 375 - | none => throw (.typeError s!"missing field: {key}") 376 - | .data (.array items), .int idx => 377 - if idx < 0 then 378 - throw (.typeError s!"negative index: {idx}") 379 - else 380 - match dataArrayGet? items idx.toNat with 381 - | some value => pure (.data value) 382 - | none => throw (RuntimeError.typeError s!"index out of bounds: {idx}") 383 - | .data _, .string _ => 384 - throw (.typeError "string dispatch expects a record") 385 - | .data _, .int _ => 386 - throw (.typeError "int dispatch expects an array") 387 - | _, _ => 388 - throw (.typeError "expected a function") 1117 + throw (.typeError "expected a function") 389 1118 390 1119 partial def eval (env : Env) : Expr → EvalM Value 391 - | .int n => pure (.int n) 1120 + | .int n => pure (.number (numericOfInt n)) 1121 + | .decimal d => pure (.number (numericOfDecimal d)) 392 1122 | .bool b => pure (.bool b) 393 1123 | .string s => pure (.string s) 394 1124 | .null => pure (.data .null) ··· 408 1138 pure (name, (← valueToData value'))) 409 1139 pure (.data (.record fields')) 410 1140 | .add lhs rhs => do 411 - let l ← expectInt (← eval env lhs) 412 - let r ← expectInt (← eval env rhs) 413 - pure (.int (l + r)) 1141 + let lVal ← eval env lhs 1142 + let rVal ← eval env rhs 1143 + match lVal, rVal with 1144 + | .number (.composite _), _ | _, .number (.composite _) => 1145 + pure (.number (.composite (.add (← valueToLazyReal lVal) (← valueToLazyReal rVal)))) 1146 + | _, _ => 1147 + pure (.number (.exact (addDecimals (← valueToDecimal lVal) (← valueToDecimal rVal)))) 414 1148 | .sub lhs rhs => do 415 - let l ← expectInt (← eval env lhs) 416 - let r ← expectInt (← eval env rhs) 417 - pure (.int (l - r)) 1149 + let lVal ← eval env lhs 1150 + let rVal ← eval env rhs 1151 + match lVal, rVal with 1152 + | .number (.composite _), _ | _, .number (.composite _) => 1153 + pure (.number (.composite (.sub (← valueToLazyReal lVal) (← valueToLazyReal rVal)))) 1154 + | _, _ => 1155 + pure (.number (.exact (subDecimals (← valueToDecimal lVal) (← valueToDecimal rVal)))) 418 1156 | .mul lhs rhs => do 419 - let l ← expectInt (← eval env lhs) 420 - let r ← expectInt (← eval env rhs) 421 - pure (.int (l * r)) 1157 + let lVal ← eval env lhs 1158 + let rVal ← eval env rhs 1159 + match lVal, rVal with 1160 + | .number (.composite _), _ | _, .number (.composite _) => 1161 + pure (.number (.composite (.mul (← valueToLazyReal lVal) (← valueToLazyReal rVal)))) 1162 + | _, _ => 1163 + pure (.number (.exact (mulDecimals (← valueToDecimal lVal) (← valueToDecimal rVal)))) 422 1164 | .div lhs rhs => do 423 - let l ← expectInt (← eval env lhs) 424 - let r ← expectInt (← eval env rhs) 425 - if r = 0 then 426 - throw .divisionByZero 427 - else 428 - pure (.int (l / r)) 1165 + let lVal ← eval env lhs 1166 + let rVal ← eval env rhs 1167 + match lVal, rVal with 1168 + | .number (.composite _), _ | _, .number (.composite _) => 1169 + pure (.number (.composite (.div (← valueToLazyReal lVal) (← valueToLazyReal rVal)))) 1170 + | _, _ => 1171 + pure (.number (.exact (← divDecimals (← valueToDecimal lVal) (← valueToDecimal rVal)))) 429 1172 | .eq lhs rhs => do 430 - let l ← expectInt (← eval env lhs) 431 - let r ← expectInt (← eval env rhs) 432 - pure (.bool (l = r)) 1173 + let l ← eval env lhs 1174 + let r ← eval env rhs 1175 + match l, r with 1176 + | .number _, .number _ => pure (.bool (rationalEq (← valueToDecimal l) (← valueToDecimal r))) 1177 + | _, _ => throw (.typeError "equality expects matching Int or Decimal operands") 433 1178 | .letE name value body => do 434 1179 let value' ← eval env value 435 1180 eval ((name, value') :: env) body ··· 464 1209 465 1210 def renderData : Data → String := renderNickelData 466 1211 1212 + def renderObservedScalar (value : Value) : Option String := 1213 + match value with 1214 + | .number (.exact q) => some s!"{q.num}/{q.den}" 1215 + | _ => none 1216 + 467 1217 def renderValue : Value → String 468 - | .int n => toString n 1218 + | value@(.number (.exact _)) => 1219 + match renderObservedScalar value with 1220 + | some rendered => rendered 1221 + | none => "<number>" 1222 + | .stability label => label 1223 + | .number (.composite (.ratioProcess q)) => s!"<process:ratio({q.num}/{q.den})>" 1224 + | .number (.composite (.decimalProcess d)) => s!"<process:decimal({renderDecimal d})>" 1225 + | .number (.composite (.generated (.exactRatio q))) => s!"<generator:ratio({q.num}/{q.den})>" 1226 + | .number (.composite (.generated (.exactDecimal d))) => s!"<generator:decimal({renderDecimal d})>" 1227 + | .number (.composite (.generated (.rationalRefiner _))) => "<generator:rational-refiner>" 1228 + | .number (.composite (.generated (.decimalRefiner _))) => "<generator:decimal-refiner>" 1229 + | .number (.composite (.generated .piChudnovsky)) => "<generator:pi[chudnovsky]>" 1230 + | .number (.composite (.generated (.sqrt d))) => s!"<generator:sqrt({renderDecimal d})>" 1231 + | .number (.composite (.generated (.add _ _))) => "<generator:add>" 1232 + | .number (.composite (.generated (.sub _ _))) => "<generator:sub>" 1233 + | .number (.composite (.generated (.mul _ _))) => "<generator:mul>" 1234 + | .number (.composite (.generated (.div _ _))) => "<generator:div>" 1235 + | .number (.composite (.exact d)) => s!"<lazy:{renderDecimal d}>" 1236 + | .number (.composite .pi) => "<lazy:pi>" 1237 + | .number (.composite (.sqrt d)) => s!"<lazy:sqrt({renderDecimal d})>" 1238 + | .number (.composite (.add _ _)) => "<lazy:add>" 1239 + | .number (.composite (.sub _ _)) => "<lazy:sub>" 1240 + | .number (.composite (.mul _ _)) => "<lazy:mul>" 1241 + | .number (.composite (.div _ _)) => "<lazy:div>" 469 1242 | .bool b => toString b 470 1243 | .string s => s!"\"{s}\"" 471 1244 | .data data => renderData data ··· 478 1251 | .builtinReadFileNickel => "<builtin:readFileNickel>" 479 1252 | .builtinParseNickel => "<builtin:parseNickel>" 480 1253 | .builtinParseJson => "<builtin:parseJson>" 1254 + | .builtinGetAturi => "<builtin:getAturi>" 481 1255 | .builtinDataGet => "<builtin:get>" 482 1256 | .builtinDataGetField _ => "<builtin:getField>" 483 1257 | .builtinDataAt => "<builtin:at>" 484 1258 | .builtinDataAtIndex _ => "<builtin:atIndex>" 485 1259 | .builtinDataAsInt => "<builtin:asInt>" 1260 + | .builtinDataAsDecimal => "<builtin:asDecimal>" 1261 + | .builtinRationalToInt => "<builtin:toInt>" 1262 + | .builtinRationalToDecimal => "<builtin:toDecimal>" 486 1263 | .builtinDataAsString => "<builtin:asString>" 487 1264 | .builtinDataAsBool => "<builtin:asBool>" 488 1265 | .builtinDataToJson => "<builtin:toJson>" 489 1266 | .builtinDataToNickel => "<builtin:toNickel>" 1267 + | .builtinRationalStability => "<builtin:rationalStability>" 1268 + | .builtinDecimalStability => "<builtin:decimalStability>" 1269 + | .builtinSqrt => "<builtin:sqrt>" 1270 + | .builtinProcess => "<builtin:process>" 1271 + | .builtinSynthesize => "<builtin:synthesize>" 1272 + | .builtinFormula => "<builtin:formula>" 1273 + | .builtinStabilize => "<builtin:stabilize>" 1274 + | .builtinStabilizeStep _ => "<builtin:stabilizeStep>" 1275 + | .builtinApprox => "<builtin:approx>" 1276 + | .builtinApproxStep _ => "<builtin:approxStep>" 1277 + | .builtinBounds => "<builtin:bounds>" 1278 + | .builtinBoundsStep _ => "<builtin:boundsStep>" 490 1279 | .closure _ _ _ => "<closure>" 491 1280 492 1281 abbrev TyEnv := List (Name × Ty) ··· 514 1303 pure () 515 1304 else 516 1305 throw (.mismatch expected actual) 1306 + 1307 + def isNumericTy : Ty → Bool 1308 + | .number | .int | .decimal | .rational | .lazyReal => true 1309 + | _ => false 517 1310 518 1311 def pureJudgment (ty : Ty) : Judgment := 519 1312 { ty := ty, effects := [] } 520 1313 521 1314 def eraseDataRefinement : Ty → Ty 522 - | .dataInt | .dataBool | .dataString | .dataNull | .dataArray _ | .dataRecord _ => .data 1315 + | .dataInt | .dataDecimal | .dataRational | .dataBool | .dataString | .dataNull | .dataArray _ | .dataRecord _ => .data 523 1316 | ty => ty 524 1317 525 1318 def canFlowTo (actual expected : Ty) : Bool := ··· 527 1320 true 528 1321 else 529 1322 match actual, expected with 1323 + | .number, .number => true 1324 + | .int, .number => true 1325 + | .decimal, .number => true 1326 + | .rational, .number => true 1327 + | .lazyReal, .number => true 1328 + | .number, .decimal => true 1329 + | .number, .rational => true 1330 + | .int, .decimal => true 1331 + | .int, .rational => true 1332 + | .decimal, .rational => true 1333 + | .rational, .decimal => true 530 1334 | .dataInt, .data => true 1335 + | .dataDecimal, .data => true 1336 + | .dataRational, .data => true 531 1337 | .dataBool, .data => true 532 1338 | .dataString, .data => true 533 1339 | .dataNull, .data => true ··· 544 1350 | .null => some .null 545 1351 | .string s => some (.string s) 546 1352 | .int n => some (.int n) 1353 + | .decimal d => some (.decimal d) 547 1354 | .bool b => some (.bool b) 548 1355 | .var name => env.lookup name 549 1356 | .arrayE items => do ··· 592 1399 | .ok body => some (.string body) 593 1400 | .error _ => none 594 1401 | _ => none 1402 + | .var "getAturi" => 1403 + let source ← evalConstData? env arg 1404 + match source with 1405 + | .string s => 1406 + match unsafeIO (Http.parseAturi s) with 1407 + | .ok rendered => 1408 + match Nickel.parse rendered with 1409 + | .ok term => some (Data.ofNickel term) 1410 + | .error _ => none 1411 + | .error _ => none 1412 + | _ => none 595 1413 | .var "readFileNickel" => 596 1414 let path ← evalConstData? env arg 597 1415 match path with ··· 623 1441 | _ => none 624 1442 625 1443 unsafe def inferType (env : TyEnv) : Expr → CheckM Judgment 626 - | .int _ => pure (pureJudgment .int) 1444 + | .int _ => pure (pureJudgment .number) 1445 + | .decimal _ => pure (pureJudgment .number) 627 1446 | .bool _ => pure (pureJudgment .bool) 628 1447 | .string _ => pure (pureJudgment .string) 629 1448 | .null => pure (pureJudgment .dataNull) ··· 638 1457 let itemJs ← items.mapM (inferType env) 639 1458 let dataTys ← itemJs.mapM (fun j => 640 1459 match j.ty with 1460 + | .number => pure .dataRational 641 1461 | .int => pure .dataInt 1462 + | .decimal => pure .dataDecimal 1463 + | .rational => pure .dataRational 642 1464 | .bool => pure .dataBool 643 1465 | .string => pure .dataString 644 1466 | .data => pure .data 645 1467 | .dataInt => pure .dataInt 1468 + | .dataDecimal => pure .dataDecimal 1469 + | .dataRational => pure .dataRational 646 1470 | .dataBool => pure .dataBool 647 1471 | .dataString => pure .dataString 648 1472 | .dataNull => pure .dataNull ··· 661 1485 let fieldJs ← fields.mapM (fun (name, value) => do pure (name, ← inferType env value)) 662 1486 let fieldTys ← fieldJs.mapM (fun (name, j) => do 663 1487 let ty ← match j.ty with 1488 + | .number => pure .dataRational 664 1489 | .int => pure .dataInt 1490 + | .decimal => pure .dataDecimal 1491 + | .rational => pure .dataRational 665 1492 | .bool => pure .dataBool 666 1493 | .string => pure .dataString 667 1494 | .data => pure .data 668 1495 | .dataInt => pure .dataInt 1496 + | .dataDecimal => pure .dataDecimal 1497 + | .dataRational => pure .dataRational 669 1498 | .dataBool => pure .dataBool 670 1499 | .dataString => pure .dataString 671 1500 | .dataNull => pure .dataNull ··· 682 1511 | .mul lhs rhs => do 683 1512 let lhsJ ← inferType env lhs 684 1513 let rhsJ ← inferType env rhs 685 - ensureType .int lhsJ.ty 686 - ensureType .int rhsJ.ty 687 - pure { ty := .int, effects := lhsJ.effects.union rhsJ.effects } 1514 + if isNumericTy lhsJ.ty && isNumericTy rhsJ.ty then 1515 + pure { 1516 + ty := .number 1517 + effects := lhsJ.effects.union rhsJ.effects 1518 + } 1519 + else 1520 + throw (.mismatch lhsJ.ty rhsJ.ty) 688 1521 | .div lhs rhs => do 689 1522 let lhsJ ← inferType env lhs 690 1523 let rhsJ ← inferType env rhs 691 - ensureType .int lhsJ.ty 692 - ensureType .int rhsJ.ty 693 - pure { 694 - ty := .int 695 - effects := (lhsJ.effects.union rhsJ.effects).insert .error 696 - } 1524 + if isNumericTy lhsJ.ty && isNumericTy rhsJ.ty then 1525 + pure { 1526 + ty := .number 1527 + effects := (lhsJ.effects.union rhsJ.effects).insert .error 1528 + } 1529 + else 1530 + throw (.mismatch lhsJ.ty rhsJ.ty) 697 1531 | .eq lhs rhs => do 698 1532 let lhsJ ← inferType env lhs 699 1533 let rhsJ ← inferType env rhs 700 - ensureType .int lhsJ.ty 701 - ensureType .int rhsJ.ty 702 - pure { ty := .bool, effects := lhsJ.effects.union rhsJ.effects } 1534 + if isNumericTy lhsJ.ty && isNumericTy rhsJ.ty then 1535 + pure { ty := .bool, effects := lhsJ.effects.union rhsJ.effects } 1536 + else 1537 + throw (.mismatch lhsJ.ty rhsJ.ty) 703 1538 | .letE name value body => do 704 1539 let valueJ ← inferType env value 705 1540 let bodyJ ← inferType ((name, valueJ.ty) :: env) body ··· 791 1626 match argJ.ty with 792 1627 | .dataInt => .int 793 1628 | _ => .int 1629 + | .var "asDecimal", _, .decimal => 1630 + match argJ.ty with 1631 + | .dataDecimal => .decimal 1632 + | _ => .decimal 1633 + | .var "toInt", _, .int => 1634 + .int 1635 + | .var "toDecimal", _, .decimal => 1636 + .decimal 794 1637 | .var "asString", _, .string => 795 1638 match argJ.ty with 796 1639 | .dataString => .string ··· 799 1642 match argJ.ty with 800 1643 | .dataBool => .bool 801 1644 | _ => .bool 1645 + | .app (.var "approx") _, _, .number => 1646 + .number 1647 + | .app (.var "stabilize") _, _, .number => 1648 + .number 1649 + | .app (.var "bounds") _, _, .data => 1650 + .data 802 1651 | _, _, _ => resultTy 803 1652 pure { 804 1653 ty := refinedResultTy ··· 810 1659 throw (.expectedFunction fnJ.ty) 811 1660 812 1661 partial def renderType : Ty → String 1662 + | .number => "Number" 813 1663 | .int => "Int" 1664 + | .decimal => "Decimal" 1665 + | .rational => "Number" 1666 + | .lazyReal => "Number" 1667 + | .stability => "Stability" 814 1668 | .bool => "Bool" 815 1669 | .string => "String" 816 1670 | .data => "Data" 817 1671 | .dataInt => "Data:Int" 1672 + | .dataDecimal => "Data:Decimal" 1673 + | .dataRational => "Data:Rational" 818 1674 | .dataBool => "Data:Bool" 819 1675 | .dataString => "Data:String" 820 1676 | .dataNull => "Data:Null" ··· 826 1682 | .result => "Result" 827 1683 | .error => "Error" 828 1684 | .funTy lhs effects rhs => s!"({renderType lhs} -> {renderType rhs} ! {effects.render})" 1685 + 1686 + def renderTypeError : TypeError → String 1687 + | .unboundVariable name => s!"unbound variable {name}" 1688 + | .mismatch expected actual => s!"expected {renderType expected}, got {renderType actual}" 1689 + | .expectedFunction actual => s!"expected function, got {renderType actual}" 829 1690 830 1691 def renderJudgment (judgment : Judgment) : String := 831 1692 s!"{renderType judgment.ty} ! {judgment.effects.render}"
+27 -4
Mlang/Nickel.lean
··· 1 1 namespace Mlang.Nickel 2 2 3 + abbrev Decimal := String 4 + 3 5 inductive Term where 4 6 | null : Term 5 7 | bool : Bool → Term 6 8 | int : Int → Term 9 + | decimal : Decimal → Term 7 10 | string : String → Term 8 11 | array : List Term → Term 9 12 | record : List (String × Term) → Term ··· 77 80 | some n => pure (n, rest) 78 81 | none => throw "invalid integer literal" 79 82 83 + def parseNumber (input : Input) : ParseM (Term × Input) := do 84 + let (sign, rest) := 85 + match input with 86 + | '-' :: tail => ("-", tail) 87 + | _ => ("", input) 88 + let (wholeDigits, rest) := spanChars isDigit rest 89 + if wholeDigits.isEmpty then 90 + throw "expected numeric literal" 91 + else 92 + match rest with 93 + | '.' :: fracRest => 94 + let (fracDigits, tail) := spanChars isDigit fracRest 95 + if fracDigits.isEmpty then 96 + throw "invalid decimal literal" 97 + else 98 + pure (.decimal (sign ++ charsToString wholeDigits ++ "." ++ charsToString fracDigits), tail) 99 + | _ => 100 + match String.toInt? (sign ++ charsToString wholeDigits) with 101 + | some n => pure (.int n, rest) 102 + | none => throw "invalid integer literal" 103 + 80 104 def parseIdent (input : Input) : ParseM (String × Input) := do 81 105 match input with 82 106 | c :: rest => ··· 107 131 | "null" => pure (.null, rest) 108 132 | _ => throw s!"unexpected identifier '{name}'" 109 133 | '-' :: _ => 110 - let (n, rest) ← parseInt input 111 - pure (.int n, rest) 134 + parseNumber input 112 135 | c :: _ => 113 136 if isDigit c then 114 - let (n, rest) ← parseInt input 115 - pure (.int n, rest) 137 + parseNumber input 116 138 else 117 139 throw s!"unexpected character '{c}'" 118 140 ··· 178 200 | .bool true => "true" 179 201 | .bool false => "false" 180 202 | .int n => toString n 203 + | .decimal d => d 181 204 | .string s => s!"\"{s}\"" 182 205 | .array xs => 183 206 "[" ++ String.intercalate ", " (xs.map render) ++ "]"
+19 -4
Mlang/Parser.lean
··· 4 4 5 5 inductive Token where 6 6 | int : Int → Token 7 + | decimal : Decimal → Token 7 8 | bool : Bool → Token 8 9 | string : String → Token 9 10 | ident : String → Token ··· 54 55 isIdentStart c || isDigit c 55 56 56 57 def isAtomStart : Token → Bool 57 - | .int _ | .bool _ | .string _ | .ident _ | .lparen | .lbracket | .lbrace | .kwNull => true 58 + | .int _ | .decimal _ | .bool _ | .string _ | .ident _ | .lparen | .lbracket | .lbrace | .kwNull => true 58 59 | _ => false 59 60 60 61 partial def spanChars (p : Char → Bool) : List Char → List Char × List Char ··· 91 92 92 93 def lexNumber (chars : List Char) : ParseM (Token × List Char) := do 93 94 let (digits, rest) := spanChars isDigit chars 94 - match String.toInt? (charsToString digits) with 95 - | some n => pure (.int n, rest) 96 - | none => throw (.lexError "invalid integer literal") 95 + match rest with 96 + | '.' :: fracRest => 97 + let (fracDigits, tail) := spanChars isDigit fracRest 98 + if fracDigits.isEmpty then 99 + throw (.lexError "invalid decimal literal") 100 + else 101 + pure (.decimal (parseDecimal (charsToString digits ++ "." ++ charsToString fracDigits)), tail) 102 + | _ => 103 + match String.toInt? (charsToString digits) with 104 + | some n => pure (.int n, rest) 105 + | none => throw (.lexError "invalid integer literal") 97 106 98 107 partial def takeStringChars : List Char → ParseM (List Char × List Char) 99 108 | [] => throw (.lexError "unterminated string literal") ··· 186 195 | _ => pure (lhs, rest) 187 196 188 197 partial def parseTyAtom : ParserState → ParseM (Ty × ParserState) 198 + | .ident "Number" :: rest => pure (.number, rest) 189 199 | .ident "Int" :: rest => pure (.int, rest) 200 + | .ident "Decimal" :: rest => pure (.decimal, rest) 201 + | .ident "Rational" :: rest => pure (.number, rest) 202 + | .ident "Stability" :: rest => pure (.stability, rest) 190 203 | .ident "Bool" :: rest => pure (.bool, rest) 204 + | .ident "LazyReal" :: rest => pure (.number, rest) 191 205 | .ident "String" :: rest => pure (.string, rest) 192 206 | .ident "Data" :: rest => pure (.data, rest) 193 207 | .ident "List" :: rest => pure (.list, rest) ··· 347 361 348 362 partial def parseAtom : ParserState → ParseM (Expr × ParserState) 349 363 | .int n :: rest => pure (.int n, rest) 364 + | .decimal d :: rest => pure (.decimal d, rest) 350 365 | .bool b :: rest => pure (.bool b, rest) 351 366 | .string s :: rest => pure (.string s, rest) 352 367 | .kwNull :: rest => pure (.null, rest)
+41 -9
README.md
··· 4 4 5 5 Current scope: 6 6 7 - - integer and boolean literals 7 + - integer, decimal, and boolean literals 8 8 - variables 9 9 - `let` 10 10 - `if` 11 11 - typed lambdas 12 12 - function application 13 - - integer arithmetic 14 - - integer division 13 + - decimal arithmetic with implicit `Int` promotion 15 14 - strings 16 15 - native parsed data values 17 16 - lexical closures ··· 68 67 | { key = expr, ... } 69 68 | null 70 69 | (expr) 71 - | true | false | 123 | "text" | name 70 + | true | false | 123 | 1.23 | "text" | name 72 71 73 72 program ::= expr (';' expr)* 74 73 75 - type ::= Int | Bool | String | Data | List | Result | Error | type -> type | (type) 74 + type ::= Int | Decimal | LazyReal | Bool | String | Data | List | Result | Error | type -> type | (type) 76 75 ``` 77 76 78 77 Inside the REPL, there is also a top-level binding form: ··· 88 87 x + 1 89 88 ``` 90 89 91 - Expressions are checked as `Type ! Effects`. Pure expressions get `{}`; division carries `{Error}` implicitly. `readFile` is a builtin with type `String -> String ! {IO, Error}`. `readFileNickel` is a builtin with type `String -> Data ! {IO, Error}`. `parseNickel` is a builtin with type `String -> Data ! {Error}` and is backed by the real Nickel Rust crate. Nickel source is evaluated on the host side and converted back into `mlang` `Data`. Parsed data inspection is available through: 90 + Expressions are checked as `Type ! Effects`. Plain numeric literals now default to `Rational`, so `1`, `1.25`, `1 + 2`, and `5 / 2` are all rational values unless you explicitly cast them. Division carries `{Error}` implicitly. `readFile` is a builtin with type `String -> String ! {IO, Error}`. `readFileNickel` is a builtin with type `String -> Data ! {IO, Error}`. `parseNickel` is a builtin with type `String -> Data ! {Error}` and is backed by the real Nickel Rust crate. Nickel source is evaluated on the host side and converted back into `mlang` `Data`. Parsed data inspection is available through: 92 91 93 92 - `httpGet : String -> String ! {IO, Error}` 94 93 - `parseJson : String -> Data ! {Error}` 95 94 96 95 - `get : Data -> String -> Data ! {Error}` 97 - - `at : Data -> Int -> Data ! {Error}` 96 + - `at : Data -> Rational -> Data ! {Error}` 98 97 - `asInt : Data -> Int ! {Error}` 98 + - `asDecimal : Data -> Decimal ! {Error}` 99 99 - `asString : Data -> String ! {Error}` 100 100 - `asBool : Data -> Bool ! {Error}` 101 + - `toInt : Rational -> Int ! {Error}` 102 + - `toDecimal : Rational -> Decimal ! {Error}` 101 103 - `toJson : Data -> String` 102 104 - `toNickel : Data -> String` 105 + - `rationalStability : Rational -> Stability` 106 + - `decimalStability : Rational -> Stability` 107 + - `sqrt : Decimal -> LazyReal ! {Error}` 108 + - `pi : LazyReal` 109 + - `lazyRationalStability : LazyReal -> Stability` 110 + - `lazyDecimalStability : LazyReal -> Stability` 111 + - `approx : LazyReal -> Rational -> Rational ! {Error}` 112 + - `bounds : LazyReal -> Rational -> Data ! {Error}` 103 113 104 114 `httpGet` is implemented through a thin Rust host library plus a small C shim for Lean FFI. The Rust layer uses a real HTTP client crate rather than spawning an external tool. 105 115 `try ... with name => ...` handles `Error`, binds the caught error as an `Error` value, and removes `Error` from the resulting effect set when recovered locally. ··· 108 118 - `null` 109 119 - booleans 110 120 - integers 121 + - decimals 111 122 - strings 112 123 - arrays 113 124 - records 114 125 115 - Non-integer numeric Nickel values are not supported yet by `mlang`'s `Data` model. 126 + Exact rational values are supported in native literals and in `Data` values coming from JSON or Nickel. 116 127 117 128 Native `Data` literals are also supported directly in `mlang`: 118 129 ··· 120 131 { answer = 42, flags = [true, false], note = "ok", empty = null } 121 132 ``` 122 133 123 - Fields and array elements may be `Int`, `Bool`, `String`, or existing `Data` expressions. 134 + Fields and array elements may be `Rational`, `Bool`, `String`, or existing `Data` expressions. 135 + 136 + `LazyReal` represents process-like numeric values that are observed through refinement. The current implementation supports decimal input to `sqrt`, while `approx` and `bounds` observe lazies as rationals: 137 + 138 + ```mlang 139 + let r = sqrt 2.0 140 + approx r 4 141 + bounds r 4 142 + approx pi 4 143 + toDecimal (approx pi 4) 144 + ``` 145 + 146 + Ordinary arithmetic lifts over `LazyReal`, so expressions like `sqrt 2.0 + 3.0` stay lazy until observed with `approx` or `bounds`. 147 + 148 + Stability observations classify how a number settles under rational and decimal observation: 149 + 150 + ```mlang 151 + rationalStability (1 / 3) -- Immediate 152 + decimalStability (1 / 3) -- Periodic 153 + lazyRationalStability pi -- Refining 154 + lazyDecimalStability (sqrt 2) -- Refining 155 + ``` 124 156 125 157 `pmap name in expr => body` expects `expr` to evaluate to a native `Data` array. It evaluates `body` concurrently for each element bound to `name`, preserves input order, and returns a native `List` of native `Result` values instead of failing the whole traversal. 126 158
+18
examples/samples.mlg
··· 1 1 let inc = fun (x : Int) => x + 1 in inc 41; 2 + 1.25; 3 + 1.25 = 1.250; 4 + 5 / 2; 5 + 1 + 2.5; 6 + toInt 2; 7 + toDecimal (1 / 2); 8 + rationalStability (1 / 3); 9 + decimalStability (1 / 3); 10 + approx (sqrt 2.0) 4; 11 + bounds (sqrt 2.0) 4; 12 + approx (sqrt 2.0 + 3.0) 4; 13 + approx pi 4; 14 + approx (pi + 1.0) 4; 15 + lazyRationalStability pi; 16 + lazyDecimalStability (sqrt 2.0); 2 17 let x = 10 in let f = fun (y : Int) => x + y in let x = 100 in f 5; 3 18 if 6 * 7 = 42 then 1 else 0; 4 19 10 / 2; ··· 6 21 readFileNickel "examples/sample.ncl"; 7 22 parseNickel "{ answer = 42, flags = [true, false], note = \"ok\" }"; 8 23 parseJson "{\"answer\":42,\"flags\":[true,false],\"note\":\"ok\",\"empty\":null}"; 24 + parseJson "{\"price\":12.50,\"tax\":0.075}"; 9 25 { answer = 42, flags = [true, false], note = "ok", empty = null }; 26 + { price = 12.50, tax = 0.075 }; 10 27 toJson (parseNickel "{ answer = 42, flags = [true, false], note = \"ok\" }"); 11 28 toJson (parseJson "{\"answer\":42,\"flags\":[true,false],\"note\":\"ok\",\"empty\":null}"); 12 29 toJson { answer = 42, flags = [true, false], note = "ok", empty = null }; 13 30 toNickel (parseJson "{\"answer\":42,\"flags\":[true,false],\"note\":\"ok\",\"odd key\":null}"); 14 31 get (parseNickel "{ answer = 42, flags = [true, false] }") "answer"; 15 32 get (parseJson "{\"answer\":42,\"flags\":[true,false]}") "answer"; 33 + get (parseJson "{\"price\":12.50}") "price"; 16 34 get { answer = 42, flags = [true, false] } "answer"; 17 35 at (get (parseNickel "{ flags = [true, false] }") "flags") 1; 18 36 -> "examples/sample.ncl" readFileNickel (get "answer");
+1734 -20
native/mlang_http/Cargo.lock
··· 33 33 checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" 34 34 35 35 [[package]] 36 + name = "allocator-api2" 37 + version = "0.2.21" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 40 + 41 + [[package]] 36 42 name = "anstream" 37 43 version = "1.0.0" 38 44 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 83 89 ] 84 90 85 91 [[package]] 92 + name = "anyhow" 93 + version = "1.0.102" 94 + source = "registry+https://github.com/rust-lang/crates.io-index" 95 + checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" 96 + 97 + [[package]] 86 98 name = "arraydeque" 87 99 version = "0.5.1" 88 100 source = "registry+https://github.com/rust-lang/crates.io-index" 89 101 checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" 90 102 91 103 [[package]] 104 + name = "arrayref" 105 + version = "0.3.9" 106 + source = "registry+https://github.com/rust-lang/crates.io-index" 107 + checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" 108 + 109 + [[package]] 92 110 name = "arrayvec" 93 111 version = "0.5.2" 94 112 source = "registry+https://github.com/rust-lang/crates.io-index" 95 113 checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 96 114 97 115 [[package]] 116 + name = "arrayvec" 117 + version = "0.7.6" 118 + source = "registry+https://github.com/rust-lang/crates.io-index" 119 + checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 120 + 121 + [[package]] 98 122 name = "ascii-canvas" 99 123 version = "4.0.0" 100 124 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 104 128 ] 105 129 106 130 [[package]] 131 + name = "async-trait" 132 + version = "0.1.89" 133 + source = "registry+https://github.com/rust-lang/crates.io-index" 134 + checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" 135 + dependencies = [ 136 + "proc-macro2", 137 + "quote", 138 + "syn", 139 + ] 140 + 141 + [[package]] 142 + name = "atomic-waker" 143 + version = "1.1.2" 144 + source = "registry+https://github.com/rust-lang/crates.io-index" 145 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 146 + 147 + [[package]] 148 + name = "atproto-client" 149 + version = "0.14.5" 150 + source = "registry+https://github.com/rust-lang/crates.io-index" 151 + checksum = "b0c1438d67d1fe2d06b5e5f8030c58cce991e074bab03b5e226a949507172f24" 152 + dependencies = [ 153 + "anyhow", 154 + "async-trait", 155 + "atproto-identity", 156 + "atproto-oauth", 157 + "atproto-record", 158 + "bytes", 159 + "reqwest", 160 + "reqwest-chain", 161 + "reqwest-middleware", 162 + "serde", 163 + "serde_json", 164 + "thiserror 2.0.18", 165 + "tokio", 166 + "tracing", 167 + "urlencoding", 168 + ] 169 + 170 + [[package]] 171 + name = "atproto-dasl" 172 + version = "0.14.5" 173 + source = "registry+https://github.com/rust-lang/crates.io-index" 174 + checksum = "a28d38577f468ab23e3351835f370cf34270caf290205a7e1520d352f5be4b28" 175 + dependencies = [ 176 + "blake3", 177 + "cid", 178 + "futures", 179 + "multihash", 180 + "serde", 181 + "serde_bytes", 182 + "sha2 0.11.0", 183 + "tempfile", 184 + "thiserror 2.0.18", 185 + "tokio", 186 + "tracing", 187 + "url", 188 + ] 189 + 190 + [[package]] 191 + name = "atproto-identity" 192 + version = "0.14.5" 193 + source = "registry+https://github.com/rust-lang/crates.io-index" 194 + checksum = "722940aeee9654eef58cdd8b70d62772357621a2587367191b1c5630742f8e77" 195 + dependencies = [ 196 + "anyhow", 197 + "async-trait", 198 + "atproto-dasl", 199 + "base64", 200 + "chrono", 201 + "data-encoding", 202 + "ecdsa", 203 + "ed25519-dalek", 204 + "elliptic-curve", 205 + "hickory-resolver", 206 + "idna", 207 + "k256", 208 + "lru", 209 + "multibase", 210 + "p256", 211 + "p384", 212 + "rand 0.10.1", 213 + "reqwest", 214 + "serde", 215 + "serde_json", 216 + "sha2 0.11.0", 217 + "thiserror 2.0.18", 218 + "tokio", 219 + "tracing", 220 + "url", 221 + ] 222 + 223 + [[package]] 224 + name = "atproto-oauth" 225 + version = "0.14.5" 226 + source = "registry+https://github.com/rust-lang/crates.io-index" 227 + checksum = "8f9b1e34b59d7d1f641dd03a2b05b5153a2a4eb2ef1b36d6d7fbbf80a4aa954b" 228 + dependencies = [ 229 + "anyhow", 230 + "async-trait", 231 + "atproto-identity", 232 + "base64", 233 + "chrono", 234 + "ecdsa", 235 + "elliptic-curve", 236 + "k256", 237 + "lru", 238 + "multibase", 239 + "p256", 240 + "p384", 241 + "rand 0.10.1", 242 + "reqwest", 243 + "reqwest-chain", 244 + "reqwest-middleware", 245 + "serde", 246 + "serde_json", 247 + "sha2 0.11.0", 248 + "thiserror 2.0.18", 249 + "tokio", 250 + "tracing", 251 + "ulid", 252 + ] 253 + 254 + [[package]] 255 + name = "atproto-record" 256 + version = "0.14.5" 257 + source = "registry+https://github.com/rust-lang/crates.io-index" 258 + checksum = "52a83494a80a9add1c3678e821f92153a4b5d139c0b6898bbf5eb97501cf2359" 259 + dependencies = [ 260 + "anyhow", 261 + "atproto-dasl", 262 + "atproto-identity", 263 + "base64", 264 + "chrono", 265 + "cid", 266 + "multihash", 267 + "rand 0.10.1", 268 + "serde", 269 + "serde_json", 270 + "sha2 0.11.0", 271 + "thiserror 2.0.18", 272 + ] 273 + 274 + [[package]] 275 + name = "autocfg" 276 + version = "1.5.1" 277 + source = "registry+https://github.com/rust-lang/crates.io-index" 278 + checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" 279 + 280 + [[package]] 107 281 name = "backtrace" 108 282 version = "0.3.76" 109 283 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 128 302 ] 129 303 130 304 [[package]] 305 + name = "base-x" 306 + version = "0.2.11" 307 + source = "registry+https://github.com/rust-lang/crates.io-index" 308 + checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" 309 + 310 + [[package]] 311 + name = "base16ct" 312 + version = "0.2.0" 313 + source = "registry+https://github.com/rust-lang/crates.io-index" 314 + checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" 315 + 316 + [[package]] 317 + name = "base256emoji" 318 + version = "1.0.2" 319 + source = "registry+https://github.com/rust-lang/crates.io-index" 320 + checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" 321 + dependencies = [ 322 + "const-str", 323 + "match-lookup", 324 + ] 325 + 326 + [[package]] 131 327 name = "base64" 132 328 version = "0.22.1" 133 329 source = "registry+https://github.com/rust-lang/crates.io-index" 134 330 checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 331 + 332 + [[package]] 333 + name = "base64ct" 334 + version = "1.8.3" 335 + source = "registry+https://github.com/rust-lang/crates.io-index" 336 + checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" 135 337 136 338 [[package]] 137 339 name = "bincode" ··· 170 372 checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" 171 373 172 374 [[package]] 375 + name = "blake3" 376 + version = "1.8.5" 377 + source = "registry+https://github.com/rust-lang/crates.io-index" 378 + checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" 379 + dependencies = [ 380 + "arrayref", 381 + "arrayvec 0.7.6", 382 + "cc", 383 + "cfg-if", 384 + "constant_time_eq", 385 + "cpufeatures 0.3.0", 386 + ] 387 + 388 + [[package]] 173 389 name = "block-buffer" 174 390 version = "0.10.4" 175 391 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 179 395 ] 180 396 181 397 [[package]] 398 + name = "block-buffer" 399 + version = "0.12.0" 400 + source = "registry+https://github.com/rust-lang/crates.io-index" 401 + checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" 402 + dependencies = [ 403 + "hybrid-array", 404 + ] 405 + 406 + [[package]] 182 407 name = "bon" 183 408 version = "3.9.1" 184 409 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 216 441 checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" 217 442 218 443 [[package]] 444 + name = "bytes" 445 + version = "1.11.1" 446 + source = "registry+https://github.com/rust-lang/crates.io-index" 447 + checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" 448 + 449 + [[package]] 219 450 name = "caseless" 220 451 version = "0.2.2" 221 452 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 247 478 checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 248 479 249 480 [[package]] 481 + name = "chacha20" 482 + version = "0.10.0" 483 + source = "registry+https://github.com/rust-lang/crates.io-index" 484 + checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" 485 + dependencies = [ 486 + "cfg-if", 487 + "cpufeatures 0.3.0", 488 + "rand_core 0.10.1", 489 + ] 490 + 491 + [[package]] 492 + name = "chrono" 493 + version = "0.4.44" 494 + source = "registry+https://github.com/rust-lang/crates.io-index" 495 + checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" 496 + dependencies = [ 497 + "num-traits", 498 + "serde", 499 + ] 500 + 501 + [[package]] 502 + name = "cid" 503 + version = "0.11.3" 504 + source = "registry+https://github.com/rust-lang/crates.io-index" 505 + checksum = "21a304f95f84d169a6f31c4d0a30d784643aaa0bbc9c1e449a2c23e963ec4971" 506 + dependencies = [ 507 + "multibase", 508 + "multihash", 509 + "unsigned-varint", 510 + ] 511 + 512 + [[package]] 250 513 name = "clap" 251 514 version = "4.6.1" 252 515 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 344 607 ] 345 608 346 609 [[package]] 610 + name = "const-oid" 611 + version = "0.9.6" 612 + source = "registry+https://github.com/rust-lang/crates.io-index" 613 + checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 614 + 615 + [[package]] 616 + name = "const-oid" 617 + version = "0.10.2" 618 + source = "registry+https://github.com/rust-lang/crates.io-index" 619 + checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" 620 + 621 + [[package]] 622 + name = "const-str" 623 + version = "0.4.3" 624 + source = "registry+https://github.com/rust-lang/crates.io-index" 625 + checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" 626 + 627 + [[package]] 628 + name = "constant_time_eq" 629 + version = "0.4.2" 630 + source = "registry+https://github.com/rust-lang/crates.io-index" 631 + checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" 632 + 633 + [[package]] 347 634 name = "convert_case" 348 635 version = "0.10.0" 349 636 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 362 649 ] 363 650 364 651 [[package]] 652 + name = "core-foundation" 653 + version = "0.9.4" 654 + source = "registry+https://github.com/rust-lang/crates.io-index" 655 + checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 656 + dependencies = [ 657 + "core-foundation-sys", 658 + "libc", 659 + ] 660 + 661 + [[package]] 662 + name = "core-foundation-sys" 663 + version = "0.8.7" 664 + source = "registry+https://github.com/rust-lang/crates.io-index" 665 + checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 666 + 667 + [[package]] 365 668 name = "cpufeatures" 366 669 version = "0.2.17" 367 670 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 371 674 ] 372 675 373 676 [[package]] 677 + name = "cpufeatures" 678 + version = "0.3.0" 679 + source = "registry+https://github.com/rust-lang/crates.io-index" 680 + checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" 681 + dependencies = [ 682 + "libc", 683 + ] 684 + 685 + [[package]] 374 686 name = "crc32fast" 375 687 version = "1.5.0" 376 688 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 378 690 dependencies = [ 379 691 "cfg-if", 380 692 ] 693 + 694 + [[package]] 695 + name = "critical-section" 696 + version = "1.2.0" 697 + source = "registry+https://github.com/rust-lang/crates.io-index" 698 + checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" 381 699 382 700 [[package]] 383 701 name = "crokey" ··· 486 804 checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 487 805 dependencies = [ 488 806 "winapi", 807 + ] 808 + 809 + [[package]] 810 + name = "crypto-bigint" 811 + version = "0.5.5" 812 + source = "registry+https://github.com/rust-lang/crates.io-index" 813 + checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" 814 + dependencies = [ 815 + "generic-array", 816 + "rand_core 0.6.4", 817 + "subtle", 818 + "zeroize", 489 819 ] 490 820 491 821 [[package]] ··· 499 829 ] 500 830 501 831 [[package]] 832 + name = "crypto-common" 833 + version = "0.2.2" 834 + source = "registry+https://github.com/rust-lang/crates.io-index" 835 + checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" 836 + dependencies = [ 837 + "hybrid-array", 838 + ] 839 + 840 + [[package]] 841 + name = "curve25519-dalek" 842 + version = "4.1.3" 843 + source = "registry+https://github.com/rust-lang/crates.io-index" 844 + checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" 845 + dependencies = [ 846 + "cfg-if", 847 + "cpufeatures 0.2.17", 848 + "curve25519-dalek-derive", 849 + "digest 0.10.7", 850 + "fiat-crypto", 851 + "rustc_version", 852 + "subtle", 853 + "zeroize", 854 + ] 855 + 856 + [[package]] 857 + name = "curve25519-dalek-derive" 858 + version = "0.1.1" 859 + source = "registry+https://github.com/rust-lang/crates.io-index" 860 + checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" 861 + dependencies = [ 862 + "proc-macro2", 863 + "quote", 864 + "syn", 865 + ] 866 + 867 + [[package]] 502 868 name = "darling" 503 869 version = "0.23.0" 504 870 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 533 899 ] 534 900 535 901 [[package]] 902 + name = "data-encoding" 903 + version = "2.11.0" 904 + source = "registry+https://github.com/rust-lang/crates.io-index" 905 + checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" 906 + 907 + [[package]] 908 + name = "data-encoding-macro" 909 + version = "0.1.20" 910 + source = "registry+https://github.com/rust-lang/crates.io-index" 911 + checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" 912 + dependencies = [ 913 + "data-encoding", 914 + "data-encoding-macro-internal", 915 + ] 916 + 917 + [[package]] 918 + name = "data-encoding-macro-internal" 919 + version = "0.1.18" 920 + source = "registry+https://github.com/rust-lang/crates.io-index" 921 + checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" 922 + dependencies = [ 923 + "data-encoding", 924 + "syn", 925 + ] 926 + 927 + [[package]] 928 + name = "der" 929 + version = "0.7.10" 930 + source = "registry+https://github.com/rust-lang/crates.io-index" 931 + checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" 932 + dependencies = [ 933 + "const-oid 0.9.6", 934 + "pem-rfc7468", 935 + "zeroize", 936 + ] 937 + 938 + [[package]] 536 939 name = "deranged" 537 940 version = "0.5.8" 538 941 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 575 978 source = "registry+https://github.com/rust-lang/crates.io-index" 576 979 checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 577 980 dependencies = [ 578 - "block-buffer", 579 - "crypto-common", 981 + "block-buffer 0.10.4", 982 + "const-oid 0.9.6", 983 + "crypto-common 0.1.7", 984 + "subtle", 985 + ] 986 + 987 + [[package]] 988 + name = "digest" 989 + version = "0.11.3" 990 + source = "registry+https://github.com/rust-lang/crates.io-index" 991 + checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" 992 + dependencies = [ 993 + "block-buffer 0.12.0", 994 + "const-oid 0.10.2", 995 + "crypto-common 0.2.2", 580 996 ] 581 997 582 998 [[package]] ··· 600 1016 ] 601 1017 602 1018 [[package]] 1019 + name = "ecdsa" 1020 + version = "0.16.9" 1021 + source = "registry+https://github.com/rust-lang/crates.io-index" 1022 + checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" 1023 + dependencies = [ 1024 + "der", 1025 + "digest 0.10.7", 1026 + "elliptic-curve", 1027 + "rfc6979", 1028 + "serdect", 1029 + "signature", 1030 + "spki", 1031 + ] 1032 + 1033 + [[package]] 1034 + name = "ed25519" 1035 + version = "2.2.3" 1036 + source = "registry+https://github.com/rust-lang/crates.io-index" 1037 + checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" 1038 + dependencies = [ 1039 + "pkcs8", 1040 + "signature", 1041 + ] 1042 + 1043 + [[package]] 1044 + name = "ed25519-dalek" 1045 + version = "2.2.0" 1046 + source = "registry+https://github.com/rust-lang/crates.io-index" 1047 + checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" 1048 + dependencies = [ 1049 + "curve25519-dalek", 1050 + "ed25519", 1051 + "rand_core 0.6.4", 1052 + "serde", 1053 + "sha2 0.10.9", 1054 + "subtle", 1055 + "zeroize", 1056 + ] 1057 + 1058 + [[package]] 603 1059 name = "either" 604 1060 version = "1.16.0" 605 1061 source = "registry+https://github.com/rust-lang/crates.io-index" 606 1062 checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" 607 1063 608 1064 [[package]] 1065 + name = "elliptic-curve" 1066 + version = "0.13.8" 1067 + source = "registry+https://github.com/rust-lang/crates.io-index" 1068 + checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" 1069 + dependencies = [ 1070 + "base16ct", 1071 + "base64ct", 1072 + "crypto-bigint", 1073 + "digest 0.10.7", 1074 + "ff", 1075 + "generic-array", 1076 + "group", 1077 + "hkdf", 1078 + "pem-rfc7468", 1079 + "pkcs8", 1080 + "rand_core 0.6.4", 1081 + "sec1", 1082 + "serde_json", 1083 + "serdect", 1084 + "subtle", 1085 + "zeroize", 1086 + ] 1087 + 1088 + [[package]] 609 1089 name = "emojis" 610 1090 version = "0.6.4" 611 1091 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 624 1104 ] 625 1105 626 1106 [[package]] 1107 + name = "encoding_rs" 1108 + version = "0.8.35" 1109 + source = "registry+https://github.com/rust-lang/crates.io-index" 1110 + checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 1111 + dependencies = [ 1112 + "cfg-if", 1113 + ] 1114 + 1115 + [[package]] 627 1116 name = "endian-type" 628 1117 version = "0.1.2" 629 1118 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 636 1125 checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" 637 1126 638 1127 [[package]] 1128 + name = "enum-as-inner" 1129 + version = "0.6.1" 1130 + source = "registry+https://github.com/rust-lang/crates.io-index" 1131 + checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" 1132 + dependencies = [ 1133 + "heck 0.5.0", 1134 + "proc-macro2", 1135 + "quote", 1136 + "syn", 1137 + ] 1138 + 1139 + [[package]] 639 1140 name = "equivalent" 640 1141 version = "1.0.2" 641 1142 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 648 1149 checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 649 1150 dependencies = [ 650 1151 "libc", 651 - "windows-sys 0.52.0", 1152 + "windows-sys 0.61.2", 652 1153 ] 653 1154 654 1155 [[package]] ··· 667 1168 "regex-automata", 668 1169 "regex-syntax", 669 1170 ] 1171 + 1172 + [[package]] 1173 + name = "fastrand" 1174 + version = "2.4.1" 1175 + source = "registry+https://github.com/rust-lang/crates.io-index" 1176 + checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" 670 1177 671 1178 [[package]] 672 1179 name = "fd-lock" ··· 676 1183 dependencies = [ 677 1184 "cfg-if", 678 1185 "rustix", 679 - "windows-sys 0.52.0", 1186 + "windows-sys 0.59.0", 680 1187 ] 1188 + 1189 + [[package]] 1190 + name = "ff" 1191 + version = "0.13.1" 1192 + source = "registry+https://github.com/rust-lang/crates.io-index" 1193 + checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" 1194 + dependencies = [ 1195 + "rand_core 0.6.4", 1196 + "subtle", 1197 + ] 1198 + 1199 + [[package]] 1200 + name = "fiat-crypto" 1201 + version = "0.2.9" 1202 + source = "registry+https://github.com/rust-lang/crates.io-index" 1203 + checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" 681 1204 682 1205 [[package]] 683 1206 name = "find-msvc-tools" ··· 830 1353 dependencies = [ 831 1354 "typenum", 832 1355 "version_check", 1356 + "zeroize", 833 1357 ] 834 1358 835 1359 [[package]] ··· 839 1363 checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" 840 1364 dependencies = [ 841 1365 "cfg-if", 1366 + "js-sys", 842 1367 "libc", 843 1368 "wasi", 1369 + "wasm-bindgen", 1370 + ] 1371 + 1372 + [[package]] 1373 + name = "getrandom" 1374 + version = "0.3.4" 1375 + source = "registry+https://github.com/rust-lang/crates.io-index" 1376 + checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" 1377 + dependencies = [ 1378 + "cfg-if", 1379 + "js-sys", 1380 + "libc", 1381 + "r-efi 5.3.0", 1382 + "wasip2", 1383 + "wasm-bindgen", 1384 + ] 1385 + 1386 + [[package]] 1387 + name = "getrandom" 1388 + version = "0.4.2" 1389 + source = "registry+https://github.com/rust-lang/crates.io-index" 1390 + checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" 1391 + dependencies = [ 1392 + "cfg-if", 1393 + "libc", 1394 + "r-efi 6.0.0", 1395 + "rand_core 0.10.1", 1396 + "wasip2", 1397 + "wasip3", 844 1398 ] 845 1399 846 1400 [[package]] ··· 850 1404 checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" 851 1405 852 1406 [[package]] 1407 + name = "group" 1408 + version = "0.13.0" 1409 + source = "registry+https://github.com/rust-lang/crates.io-index" 1410 + checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" 1411 + dependencies = [ 1412 + "ff", 1413 + "rand_core 0.6.4", 1414 + "subtle", 1415 + ] 1416 + 1417 + [[package]] 1418 + name = "h2" 1419 + version = "0.4.14" 1420 + source = "registry+https://github.com/rust-lang/crates.io-index" 1421 + checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" 1422 + dependencies = [ 1423 + "atomic-waker", 1424 + "bytes", 1425 + "fnv", 1426 + "futures-core", 1427 + "futures-sink", 1428 + "http", 1429 + "indexmap", 1430 + "slab", 1431 + "tokio", 1432 + "tokio-util", 1433 + "tracing", 1434 + ] 1435 + 1436 + [[package]] 853 1437 name = "hashbrown" 854 1438 version = "0.15.5" 855 1439 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 864 1448 source = "registry+https://github.com/rust-lang/crates.io-index" 865 1449 checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 866 1450 dependencies = [ 1451 + "allocator-api2", 1452 + "equivalent", 867 1453 "foldhash 0.2.0", 868 1454 ] 869 1455 ··· 893 1479 version = "0.5.0" 894 1480 source = "registry+https://github.com/rust-lang/crates.io-index" 895 1481 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1482 + 1483 + [[package]] 1484 + name = "hickory-proto" 1485 + version = "0.25.2" 1486 + source = "registry+https://github.com/rust-lang/crates.io-index" 1487 + checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" 1488 + dependencies = [ 1489 + "async-trait", 1490 + "cfg-if", 1491 + "data-encoding", 1492 + "enum-as-inner", 1493 + "futures-channel", 1494 + "futures-io", 1495 + "futures-util", 1496 + "idna", 1497 + "ipnet", 1498 + "once_cell", 1499 + "rand 0.9.4", 1500 + "ring", 1501 + "thiserror 2.0.18", 1502 + "tinyvec", 1503 + "tokio", 1504 + "tracing", 1505 + "url", 1506 + ] 1507 + 1508 + [[package]] 1509 + name = "hickory-resolver" 1510 + version = "0.25.2" 1511 + source = "registry+https://github.com/rust-lang/crates.io-index" 1512 + checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" 1513 + dependencies = [ 1514 + "cfg-if", 1515 + "futures-util", 1516 + "hickory-proto", 1517 + "ipconfig", 1518 + "moka", 1519 + "once_cell", 1520 + "parking_lot", 1521 + "rand 0.9.4", 1522 + "resolv-conf", 1523 + "smallvec", 1524 + "thiserror 2.0.18", 1525 + "tokio", 1526 + "tracing", 1527 + ] 1528 + 1529 + [[package]] 1530 + name = "hkdf" 1531 + version = "0.12.4" 1532 + source = "registry+https://github.com/rust-lang/crates.io-index" 1533 + checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 1534 + dependencies = [ 1535 + "hmac", 1536 + ] 1537 + 1538 + [[package]] 1539 + name = "hmac" 1540 + version = "0.12.1" 1541 + source = "registry+https://github.com/rust-lang/crates.io-index" 1542 + checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1543 + dependencies = [ 1544 + "digest 0.10.7", 1545 + ] 896 1546 897 1547 [[package]] 898 1548 name = "home" ··· 904 1554 ] 905 1555 906 1556 [[package]] 1557 + name = "http" 1558 + version = "1.4.1" 1559 + source = "registry+https://github.com/rust-lang/crates.io-index" 1560 + checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" 1561 + dependencies = [ 1562 + "bytes", 1563 + "itoa", 1564 + ] 1565 + 1566 + [[package]] 1567 + name = "http-body" 1568 + version = "1.0.1" 1569 + source = "registry+https://github.com/rust-lang/crates.io-index" 1570 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 1571 + dependencies = [ 1572 + "bytes", 1573 + "http", 1574 + ] 1575 + 1576 + [[package]] 1577 + name = "http-body-util" 1578 + version = "0.1.3" 1579 + source = "registry+https://github.com/rust-lang/crates.io-index" 1580 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 1581 + dependencies = [ 1582 + "bytes", 1583 + "futures-core", 1584 + "http", 1585 + "http-body", 1586 + "pin-project-lite", 1587 + ] 1588 + 1589 + [[package]] 1590 + name = "httparse" 1591 + version = "1.10.1" 1592 + source = "registry+https://github.com/rust-lang/crates.io-index" 1593 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 1594 + 1595 + [[package]] 1596 + name = "hybrid-array" 1597 + version = "0.4.12" 1598 + source = "registry+https://github.com/rust-lang/crates.io-index" 1599 + checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" 1600 + dependencies = [ 1601 + "typenum", 1602 + ] 1603 + 1604 + [[package]] 1605 + name = "hyper" 1606 + version = "1.10.1" 1607 + source = "registry+https://github.com/rust-lang/crates.io-index" 1608 + checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" 1609 + dependencies = [ 1610 + "atomic-waker", 1611 + "bytes", 1612 + "futures-channel", 1613 + "futures-core", 1614 + "h2", 1615 + "http", 1616 + "http-body", 1617 + "httparse", 1618 + "itoa", 1619 + "pin-project-lite", 1620 + "smallvec", 1621 + "tokio", 1622 + "want", 1623 + ] 1624 + 1625 + [[package]] 1626 + name = "hyper-rustls" 1627 + version = "0.27.9" 1628 + source = "registry+https://github.com/rust-lang/crates.io-index" 1629 + checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" 1630 + dependencies = [ 1631 + "http", 1632 + "hyper", 1633 + "hyper-util", 1634 + "rustls", 1635 + "tokio", 1636 + "tokio-rustls", 1637 + "tower-service", 1638 + "webpki-roots 1.0.7", 1639 + ] 1640 + 1641 + [[package]] 1642 + name = "hyper-util" 1643 + version = "0.1.20" 1644 + source = "registry+https://github.com/rust-lang/crates.io-index" 1645 + checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" 1646 + dependencies = [ 1647 + "base64", 1648 + "bytes", 1649 + "futures-channel", 1650 + "futures-util", 1651 + "http", 1652 + "http-body", 1653 + "hyper", 1654 + "ipnet", 1655 + "libc", 1656 + "percent-encoding", 1657 + "pin-project-lite", 1658 + "socket2", 1659 + "system-configuration", 1660 + "tokio", 1661 + "tower-service", 1662 + "tracing", 1663 + "windows-registry", 1664 + ] 1665 + 1666 + [[package]] 907 1667 name = "icu_collections" 908 1668 version = "2.2.0" 909 1669 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 986 1746 ] 987 1747 988 1748 [[package]] 1749 + name = "id-arena" 1750 + version = "2.3.0" 1751 + source = "registry+https://github.com/rust-lang/crates.io-index" 1752 + checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" 1753 + 1754 + [[package]] 989 1755 name = "ident_case" 990 1756 version = "1.0.1" 991 1757 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1043 1809 ] 1044 1810 1045 1811 [[package]] 1812 + name = "ipconfig" 1813 + version = "0.3.4" 1814 + source = "registry+https://github.com/rust-lang/crates.io-index" 1815 + checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222" 1816 + dependencies = [ 1817 + "socket2", 1818 + "widestring", 1819 + "windows-registry", 1820 + "windows-result", 1821 + "windows-sys 0.61.2", 1822 + ] 1823 + 1824 + [[package]] 1825 + name = "ipnet" 1826 + version = "2.12.0" 1827 + source = "registry+https://github.com/rust-lang/crates.io-index" 1828 + checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" 1829 + 1830 + [[package]] 1046 1831 name = "is_ci" 1047 1832 version = "1.2.0" 1048 1833 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1104 1889 ] 1105 1890 1106 1891 [[package]] 1892 + name = "k256" 1893 + version = "0.13.4" 1894 + source = "registry+https://github.com/rust-lang/crates.io-index" 1895 + checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" 1896 + dependencies = [ 1897 + "cfg-if", 1898 + "ecdsa", 1899 + "elliptic-curve", 1900 + "once_cell", 1901 + "sha2 0.10.9", 1902 + "signature", 1903 + ] 1904 + 1905 + [[package]] 1107 1906 name = "keccak" 1108 1907 version = "0.1.6" 1109 1908 source = "registry+https://github.com/rust-lang/crates.io-index" 1110 1909 checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" 1111 1910 dependencies = [ 1112 - "cpufeatures", 1911 + "cpufeatures 0.2.17", 1113 1912 ] 1114 1913 1115 1914 [[package]] ··· 1168 1967 ] 1169 1968 1170 1969 [[package]] 1970 + name = "leb128fmt" 1971 + version = "0.1.0" 1972 + source = "registry+https://github.com/rust-lang/crates.io-index" 1973 + checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" 1974 + 1975 + [[package]] 1171 1976 name = "libc" 1172 1977 version = "0.2.186" 1173 1978 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1251 2056 ] 1252 2057 1253 2058 [[package]] 2059 + name = "lru" 2060 + version = "0.16.4" 2061 + source = "registry+https://github.com/rust-lang/crates.io-index" 2062 + checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" 2063 + dependencies = [ 2064 + "hashbrown 0.16.1", 2065 + ] 2066 + 2067 + [[package]] 2068 + name = "lru-slab" 2069 + version = "0.1.2" 2070 + source = "registry+https://github.com/rust-lang/crates.io-index" 2071 + checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 2072 + 2073 + [[package]] 1254 2074 name = "malachite" 1255 2075 version = "0.9.1" 1256 2076 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1313 2133 ] 1314 2134 1315 2135 [[package]] 2136 + name = "match-lookup" 2137 + version = "0.1.2" 2138 + source = "registry+https://github.com/rust-lang/crates.io-index" 2139 + checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" 2140 + dependencies = [ 2141 + "proc-macro2", 2142 + "quote", 2143 + "syn", 2144 + ] 2145 + 2146 + [[package]] 1316 2147 name = "md-5" 1317 2148 version = "0.10.6" 1318 2149 source = "registry+https://github.com/rust-lang/crates.io-index" 1319 2150 checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1320 2151 dependencies = [ 1321 2152 "cfg-if", 1322 - "digest", 2153 + "digest 0.10.7", 1323 2154 ] 1324 2155 1325 2156 [[package]] ··· 1359 2190 ] 1360 2191 1361 2192 [[package]] 2193 + name = "mime" 2194 + version = "0.3.17" 2195 + source = "registry+https://github.com/rust-lang/crates.io-index" 2196 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 2197 + 2198 + [[package]] 2199 + name = "mime_guess" 2200 + version = "2.0.5" 2201 + source = "registry+https://github.com/rust-lang/crates.io-index" 2202 + checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 2203 + dependencies = [ 2204 + "mime", 2205 + "unicase", 2206 + ] 2207 + 2208 + [[package]] 1362 2209 name = "minimad" 1363 2210 version = "0.14.0" 1364 2211 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1393 2240 name = "mlang_http" 1394 2241 version = "0.1.0" 1395 2242 dependencies = [ 2243 + "atproto-client", 2244 + "atproto-identity", 2245 + "atproto-record", 1396 2246 "nickel-lang-core", 2247 + "reqwest", 1397 2248 "serde_json", 2249 + "tokio", 1398 2250 "ureq", 1399 2251 ] 1400 2252 1401 2253 [[package]] 2254 + name = "moka" 2255 + version = "0.12.15" 2256 + source = "registry+https://github.com/rust-lang/crates.io-index" 2257 + checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" 2258 + dependencies = [ 2259 + "crossbeam-channel", 2260 + "crossbeam-epoch", 2261 + "crossbeam-utils", 2262 + "equivalent", 2263 + "parking_lot", 2264 + "portable-atomic", 2265 + "smallvec", 2266 + "tagptr", 2267 + "uuid", 2268 + ] 2269 + 2270 + [[package]] 2271 + name = "multibase" 2272 + version = "0.9.2" 2273 + source = "registry+https://github.com/rust-lang/crates.io-index" 2274 + checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" 2275 + dependencies = [ 2276 + "base-x", 2277 + "base256emoji", 2278 + "data-encoding", 2279 + "data-encoding-macro", 2280 + ] 2281 + 2282 + [[package]] 2283 + name = "multihash" 2284 + version = "0.19.5" 2285 + source = "registry+https://github.com/rust-lang/crates.io-index" 2286 + checksum = "577c63b00ad74d57e8c9aa870b5fccebf2fd64a308a5aee9f1bb88e4aea19447" 2287 + dependencies = [ 2288 + "unsigned-varint", 2289 + ] 2290 + 2291 + [[package]] 1402 2292 name = "new_debug_unreachable" 1403 2293 version = "1.0.6" 1404 2294 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1449 2339 "serde_json", 1450 2340 "serde_yaml", 1451 2341 "sha-1", 1452 - "sha2", 2342 + "sha2 0.10.9", 1453 2343 "simple-counter", 1454 2344 "smallvec", 1455 2345 "strip-ansi-escapes", ··· 1519 2409 checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" 1520 2410 1521 2411 [[package]] 2412 + name = "num-traits" 2413 + version = "0.2.19" 2414 + source = "registry+https://github.com/rust-lang/crates.io-index" 2415 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 2416 + dependencies = [ 2417 + "autocfg", 2418 + ] 2419 + 2420 + [[package]] 1522 2421 name = "object" 1523 2422 version = "0.37.3" 1524 2423 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1532 2431 version = "1.21.4" 1533 2432 source = "registry+https://github.com/rust-lang/crates.io-index" 1534 2433 checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" 2434 + dependencies = [ 2435 + "critical-section", 2436 + "portable-atomic", 2437 + ] 1535 2438 1536 2439 [[package]] 1537 2440 name = "once_cell_polyfill" ··· 1592 2495 checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" 1593 2496 1594 2497 [[package]] 2498 + name = "p256" 2499 + version = "0.13.2" 2500 + source = "registry+https://github.com/rust-lang/crates.io-index" 2501 + checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" 2502 + dependencies = [ 2503 + "ecdsa", 2504 + "elliptic-curve", 2505 + "primeorder", 2506 + "serdect", 2507 + "sha2 0.10.9", 2508 + ] 2509 + 2510 + [[package]] 2511 + name = "p384" 2512 + version = "0.13.1" 2513 + source = "registry+https://github.com/rust-lang/crates.io-index" 2514 + checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" 2515 + dependencies = [ 2516 + "ecdsa", 2517 + "elliptic-curve", 2518 + "primeorder", 2519 + "serdect", 2520 + "sha2 0.10.9", 2521 + ] 2522 + 2523 + [[package]] 1595 2524 name = "parking_lot" 1596 2525 version = "0.12.5" 1597 2526 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1621 2550 checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1622 2551 1623 2552 [[package]] 2553 + name = "pem-rfc7468" 2554 + version = "0.7.0" 2555 + source = "registry+https://github.com/rust-lang/crates.io-index" 2556 + checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 2557 + dependencies = [ 2558 + "base64ct", 2559 + ] 2560 + 2561 + [[package]] 1624 2562 name = "percent-encoding" 1625 2563 version = "2.3.2" 1626 2564 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1667 2605 checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" 1668 2606 1669 2607 [[package]] 2608 + name = "pkcs8" 2609 + version = "0.10.2" 2610 + source = "registry+https://github.com/rust-lang/crates.io-index" 2611 + checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 2612 + dependencies = [ 2613 + "der", 2614 + "spki", 2615 + ] 2616 + 2617 + [[package]] 1670 2618 name = "pkg-config" 1671 2619 version = "0.3.33" 1672 2620 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1686 2634 ] 1687 2635 1688 2636 [[package]] 2637 + name = "portable-atomic" 2638 + version = "1.13.1" 2639 + source = "registry+https://github.com/rust-lang/crates.io-index" 2640 + checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" 2641 + 2642 + [[package]] 1689 2643 name = "potential_utf" 1690 2644 version = "0.1.5" 1691 2645 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1701 2655 checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1702 2656 1703 2657 [[package]] 2658 + name = "ppv-lite86" 2659 + version = "0.2.21" 2660 + source = "registry+https://github.com/rust-lang/crates.io-index" 2661 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 2662 + dependencies = [ 2663 + "zerocopy", 2664 + ] 2665 + 2666 + [[package]] 1704 2667 name = "precomputed-hash" 1705 2668 version = "0.1.1" 1706 2669 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1712 2675 source = "registry+https://github.com/rust-lang/crates.io-index" 1713 2676 checksum = "0d22152487193190344590e4f30e219cf3fe140d9e7a3fdb683d82aa2c5f4156" 1714 2677 dependencies = [ 1715 - "arrayvec", 2678 + "arrayvec 0.5.2", 1716 2679 "typed-arena", 1717 2680 "unicode-width 0.2.2", 1718 2681 ] ··· 1747 2710 ] 1748 2711 1749 2712 [[package]] 2713 + name = "primeorder" 2714 + version = "0.13.6" 2715 + source = "registry+https://github.com/rust-lang/crates.io-index" 2716 + checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" 2717 + dependencies = [ 2718 + "elliptic-curve", 2719 + "serdect", 2720 + ] 2721 + 2722 + [[package]] 1750 2723 name = "proc-macro2" 1751 2724 version = "1.0.106" 1752 2725 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1778 2751 ] 1779 2752 1780 2753 [[package]] 2754 + name = "quinn" 2755 + version = "0.11.9" 2756 + source = "registry+https://github.com/rust-lang/crates.io-index" 2757 + checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" 2758 + dependencies = [ 2759 + "bytes", 2760 + "cfg_aliases", 2761 + "pin-project-lite", 2762 + "quinn-proto", 2763 + "quinn-udp", 2764 + "rustc-hash", 2765 + "rustls", 2766 + "socket2", 2767 + "thiserror 2.0.18", 2768 + "tokio", 2769 + "tracing", 2770 + "web-time", 2771 + ] 2772 + 2773 + [[package]] 2774 + name = "quinn-proto" 2775 + version = "0.11.14" 2776 + source = "registry+https://github.com/rust-lang/crates.io-index" 2777 + checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" 2778 + dependencies = [ 2779 + "bytes", 2780 + "getrandom 0.3.4", 2781 + "lru-slab", 2782 + "rand 0.9.4", 2783 + "ring", 2784 + "rustc-hash", 2785 + "rustls", 2786 + "rustls-pki-types", 2787 + "slab", 2788 + "thiserror 2.0.18", 2789 + "tinyvec", 2790 + "tracing", 2791 + "web-time", 2792 + ] 2793 + 2794 + [[package]] 2795 + name = "quinn-udp" 2796 + version = "0.5.14" 2797 + source = "registry+https://github.com/rust-lang/crates.io-index" 2798 + checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" 2799 + dependencies = [ 2800 + "cfg_aliases", 2801 + "libc", 2802 + "once_cell", 2803 + "socket2", 2804 + "tracing", 2805 + "windows-sys 0.59.0", 2806 + ] 2807 + 2808 + [[package]] 1781 2809 name = "quote" 1782 2810 version = "1.0.45" 1783 2811 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1785 2813 dependencies = [ 1786 2814 "proc-macro2", 1787 2815 ] 2816 + 2817 + [[package]] 2818 + name = "r-efi" 2819 + version = "5.3.0" 2820 + source = "registry+https://github.com/rust-lang/crates.io-index" 2821 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 2822 + 2823 + [[package]] 2824 + name = "r-efi" 2825 + version = "6.0.0" 2826 + source = "registry+https://github.com/rust-lang/crates.io-index" 2827 + checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" 1788 2828 1789 2829 [[package]] 1790 2830 name = "radix_trie" ··· 1797 2837 ] 1798 2838 1799 2839 [[package]] 2840 + name = "rand" 2841 + version = "0.9.4" 2842 + source = "registry+https://github.com/rust-lang/crates.io-index" 2843 + checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" 2844 + dependencies = [ 2845 + "rand_chacha", 2846 + "rand_core 0.9.5", 2847 + ] 2848 + 2849 + [[package]] 2850 + name = "rand" 2851 + version = "0.10.1" 2852 + source = "registry+https://github.com/rust-lang/crates.io-index" 2853 + checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" 2854 + dependencies = [ 2855 + "chacha20", 2856 + "getrandom 0.4.2", 2857 + "rand_core 0.10.1", 2858 + ] 2859 + 2860 + [[package]] 2861 + name = "rand_chacha" 2862 + version = "0.9.0" 2863 + source = "registry+https://github.com/rust-lang/crates.io-index" 2864 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 2865 + dependencies = [ 2866 + "ppv-lite86", 2867 + "rand_core 0.9.5", 2868 + ] 2869 + 2870 + [[package]] 2871 + name = "rand_core" 2872 + version = "0.6.4" 2873 + source = "registry+https://github.com/rust-lang/crates.io-index" 2874 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2875 + dependencies = [ 2876 + "getrandom 0.2.17", 2877 + ] 2878 + 2879 + [[package]] 2880 + name = "rand_core" 2881 + version = "0.9.5" 2882 + source = "registry+https://github.com/rust-lang/crates.io-index" 2883 + checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" 2884 + dependencies = [ 2885 + "getrandom 0.3.4", 2886 + ] 2887 + 2888 + [[package]] 2889 + name = "rand_core" 2890 + version = "0.10.1" 2891 + source = "registry+https://github.com/rust-lang/crates.io-index" 2892 + checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" 2893 + 2894 + [[package]] 1800 2895 name = "rayon" 1801 2896 version = "1.12.0" 1802 2897 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1855 2950 checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" 1856 2951 1857 2952 [[package]] 2953 + name = "reqwest" 2954 + version = "0.12.28" 2955 + source = "registry+https://github.com/rust-lang/crates.io-index" 2956 + checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" 2957 + dependencies = [ 2958 + "base64", 2959 + "bytes", 2960 + "encoding_rs", 2961 + "futures-core", 2962 + "futures-util", 2963 + "h2", 2964 + "http", 2965 + "http-body", 2966 + "http-body-util", 2967 + "hyper", 2968 + "hyper-rustls", 2969 + "hyper-util", 2970 + "js-sys", 2971 + "log", 2972 + "mime", 2973 + "mime_guess", 2974 + "percent-encoding", 2975 + "pin-project-lite", 2976 + "quinn", 2977 + "rustls", 2978 + "rustls-pki-types", 2979 + "serde", 2980 + "serde_json", 2981 + "serde_urlencoded", 2982 + "sync_wrapper", 2983 + "tokio", 2984 + "tokio-rustls", 2985 + "tower", 2986 + "tower-http", 2987 + "tower-service", 2988 + "url", 2989 + "wasm-bindgen", 2990 + "wasm-bindgen-futures", 2991 + "web-sys", 2992 + "webpki-roots 1.0.7", 2993 + ] 2994 + 2995 + [[package]] 2996 + name = "reqwest-chain" 2997 + version = "1.0.0" 2998 + source = "registry+https://github.com/rust-lang/crates.io-index" 2999 + checksum = "da5c014fb79a8227db44a0433d748107750d2550b7fca55c59a3d7ee7d2ee2b2" 3000 + dependencies = [ 3001 + "anyhow", 3002 + "async-trait", 3003 + "http", 3004 + "reqwest-middleware", 3005 + ] 3006 + 3007 + [[package]] 3008 + name = "reqwest-middleware" 3009 + version = "0.4.2" 3010 + source = "registry+https://github.com/rust-lang/crates.io-index" 3011 + checksum = "57f17d28a6e6acfe1733fe24bcd30774d13bffa4b8a22535b4c8c98423088d4e" 3012 + dependencies = [ 3013 + "anyhow", 3014 + "async-trait", 3015 + "http", 3016 + "reqwest", 3017 + "serde", 3018 + "thiserror 1.0.69", 3019 + "tower-service", 3020 + ] 3021 + 3022 + [[package]] 3023 + name = "resolv-conf" 3024 + version = "0.7.6" 3025 + source = "registry+https://github.com/rust-lang/crates.io-index" 3026 + checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" 3027 + 3028 + [[package]] 3029 + name = "rfc6979" 3030 + version = "0.4.0" 3031 + source = "registry+https://github.com/rust-lang/crates.io-index" 3032 + checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" 3033 + dependencies = [ 3034 + "hmac", 3035 + "subtle", 3036 + ] 3037 + 3038 + [[package]] 1858 3039 name = "ring" 1859 3040 version = "0.17.14" 1860 3041 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1862 3043 dependencies = [ 1863 3044 "cc", 1864 3045 "cfg-if", 1865 - "getrandom", 3046 + "getrandom 0.2.17", 1866 3047 "libc", 1867 3048 "untrusted", 1868 3049 "windows-sys 0.52.0", ··· 1875 3056 checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" 1876 3057 1877 3058 [[package]] 3059 + name = "rustc-hash" 3060 + version = "2.1.2" 3061 + source = "registry+https://github.com/rust-lang/crates.io-index" 3062 + checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" 3063 + 3064 + [[package]] 1878 3065 name = "rustc_version" 1879 3066 version = "0.4.1" 1880 3067 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1893 3080 "errno", 1894 3081 "libc", 1895 3082 "linux-raw-sys", 1896 - "windows-sys 0.52.0", 3083 + "windows-sys 0.61.2", 1897 3084 ] 1898 3085 1899 3086 [[package]] ··· 1917 3104 source = "registry+https://github.com/rust-lang/crates.io-index" 1918 3105 checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" 1919 3106 dependencies = [ 3107 + "web-time", 1920 3108 "zeroize", 1921 3109 ] 1922 3110 ··· 2011 3199 checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2012 3200 2013 3201 [[package]] 3202 + name = "sec1" 3203 + version = "0.7.3" 3204 + source = "registry+https://github.com/rust-lang/crates.io-index" 3205 + checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" 3206 + dependencies = [ 3207 + "base16ct", 3208 + "der", 3209 + "generic-array", 3210 + "pkcs8", 3211 + "serdect", 3212 + "subtle", 3213 + "zeroize", 3214 + ] 3215 + 3216 + [[package]] 2014 3217 name = "semver" 2015 3218 version = "1.0.28" 2016 3219 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2024 3227 dependencies = [ 2025 3228 "serde_core", 2026 3229 "serde_derive", 3230 + ] 3231 + 3232 + [[package]] 3233 + name = "serde_bytes" 3234 + version = "0.11.19" 3235 + source = "registry+https://github.com/rust-lang/crates.io-index" 3236 + checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" 3237 + dependencies = [ 3238 + "serde", 3239 + "serde_core", 2027 3240 ] 2028 3241 2029 3242 [[package]] ··· 2070 3283 ] 2071 3284 2072 3285 [[package]] 3286 + name = "serde_urlencoded" 3287 + version = "0.7.1" 3288 + source = "registry+https://github.com/rust-lang/crates.io-index" 3289 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 3290 + dependencies = [ 3291 + "form_urlencoded", 3292 + "itoa", 3293 + "ryu", 3294 + "serde", 3295 + ] 3296 + 3297 + [[package]] 2073 3298 name = "serde_yaml" 2074 3299 version = "0.9.34+deprecated" 2075 3300 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2083 3308 ] 2084 3309 2085 3310 [[package]] 3311 + name = "serdect" 3312 + version = "0.2.0" 3313 + source = "registry+https://github.com/rust-lang/crates.io-index" 3314 + checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" 3315 + dependencies = [ 3316 + "base16ct", 3317 + "serde", 3318 + ] 3319 + 3320 + [[package]] 2086 3321 name = "sha-1" 2087 3322 version = "0.10.1" 2088 3323 source = "registry+https://github.com/rust-lang/crates.io-index" 2089 3324 checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" 2090 3325 dependencies = [ 2091 3326 "cfg-if", 2092 - "cpufeatures", 2093 - "digest", 3327 + "cpufeatures 0.2.17", 3328 + "digest 0.10.7", 2094 3329 ] 2095 3330 2096 3331 [[package]] ··· 2100 3335 checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 2101 3336 dependencies = [ 2102 3337 "cfg-if", 2103 - "cpufeatures", 2104 - "digest", 3338 + "cpufeatures 0.2.17", 3339 + "digest 0.10.7", 3340 + ] 3341 + 3342 + [[package]] 3343 + name = "sha2" 3344 + version = "0.11.0" 3345 + source = "registry+https://github.com/rust-lang/crates.io-index" 3346 + checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" 3347 + dependencies = [ 3348 + "cfg-if", 3349 + "cpufeatures 0.3.0", 3350 + "digest 0.11.3", 2105 3351 ] 2106 3352 2107 3353 [[package]] ··· 2110 3356 source = "registry+https://github.com/rust-lang/crates.io-index" 2111 3357 checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" 2112 3358 dependencies = [ 2113 - "digest", 3359 + "digest 0.10.7", 2114 3360 "keccak", 2115 3361 ] 2116 3362 ··· 2158 3404 ] 2159 3405 2160 3406 [[package]] 3407 + name = "signature" 3408 + version = "2.2.0" 3409 + source = "registry+https://github.com/rust-lang/crates.io-index" 3410 + checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 3411 + dependencies = [ 3412 + "digest 0.10.7", 3413 + "rand_core 0.6.4", 3414 + ] 3415 + 3416 + [[package]] 2161 3417 name = "simd-adler32" 2162 3418 version = "0.3.9" 2163 3419 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2188 3444 checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 2189 3445 2190 3446 [[package]] 3447 + name = "socket2" 3448 + version = "0.6.4" 3449 + source = "registry+https://github.com/rust-lang/crates.io-index" 3450 + checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" 3451 + dependencies = [ 3452 + "libc", 3453 + "windows-sys 0.61.2", 3454 + ] 3455 + 3456 + [[package]] 3457 + name = "spki" 3458 + version = "0.7.3" 3459 + source = "registry+https://github.com/rust-lang/crates.io-index" 3460 + checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 3461 + dependencies = [ 3462 + "base64ct", 3463 + "der", 3464 + ] 3465 + 3466 + [[package]] 2191 3467 name = "stable_deref_trait" 2192 3468 version = "1.2.1" 2193 3469 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2277 3553 ] 2278 3554 2279 3555 [[package]] 3556 + name = "sync_wrapper" 3557 + version = "1.0.2" 3558 + source = "registry+https://github.com/rust-lang/crates.io-index" 3559 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 3560 + dependencies = [ 3561 + "futures-core", 3562 + ] 3563 + 3564 + [[package]] 2280 3565 name = "synstructure" 2281 3566 version = "0.13.2" 2282 3567 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2304 3589 "serde", 2305 3590 "serde_derive", 2306 3591 "serde_json", 2307 - "thiserror", 3592 + "thiserror 2.0.18", 2308 3593 "walkdir", 2309 3594 "yaml-rust", 2310 3595 ] 2311 3596 2312 3597 [[package]] 3598 + name = "system-configuration" 3599 + version = "0.7.0" 3600 + source = "registry+https://github.com/rust-lang/crates.io-index" 3601 + checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" 3602 + dependencies = [ 3603 + "bitflags", 3604 + "core-foundation", 3605 + "system-configuration-sys", 3606 + ] 3607 + 3608 + [[package]] 3609 + name = "system-configuration-sys" 3610 + version = "0.6.0" 3611 + source = "registry+https://github.com/rust-lang/crates.io-index" 3612 + checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 3613 + dependencies = [ 3614 + "core-foundation-sys", 3615 + "libc", 3616 + ] 3617 + 3618 + [[package]] 3619 + name = "tagptr" 3620 + version = "0.2.0" 3621 + source = "registry+https://github.com/rust-lang/crates.io-index" 3622 + checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" 3623 + 3624 + [[package]] 3625 + name = "tempfile" 3626 + version = "3.27.0" 3627 + source = "registry+https://github.com/rust-lang/crates.io-index" 3628 + checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" 3629 + dependencies = [ 3630 + "fastrand", 3631 + "getrandom 0.4.2", 3632 + "once_cell", 3633 + "rustix", 3634 + "windows-sys 0.61.2", 3635 + ] 3636 + 3637 + [[package]] 2313 3638 name = "term" 2314 3639 version = "1.2.1" 2315 3640 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2339 3664 "lazy-regex", 2340 3665 "minimad", 2341 3666 "serde", 2342 - "thiserror", 3667 + "thiserror 2.0.18", 2343 3668 "unicode-width 0.1.14", 2344 3669 ] 2345 3670 ··· 2365 3690 2366 3691 [[package]] 2367 3692 name = "thiserror" 3693 + version = "1.0.69" 3694 + source = "registry+https://github.com/rust-lang/crates.io-index" 3695 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 3696 + dependencies = [ 3697 + "thiserror-impl 1.0.69", 3698 + ] 3699 + 3700 + [[package]] 3701 + name = "thiserror" 2368 3702 version = "2.0.18" 2369 3703 source = "registry+https://github.com/rust-lang/crates.io-index" 2370 3704 checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" 2371 3705 dependencies = [ 2372 - "thiserror-impl", 3706 + "thiserror-impl 2.0.18", 3707 + ] 3708 + 3709 + [[package]] 3710 + name = "thiserror-impl" 3711 + version = "1.0.69" 3712 + source = "registry+https://github.com/rust-lang/crates.io-index" 3713 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 3714 + dependencies = [ 3715 + "proc-macro2", 3716 + "quote", 3717 + "syn", 2373 3718 ] 2374 3719 2375 3720 [[package]] ··· 2445 3790 source = "registry+https://github.com/rust-lang/crates.io-index" 2446 3791 checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" 2447 3792 dependencies = [ 3793 + "bytes", 3794 + "libc", 3795 + "mio", 2448 3796 "pin-project-lite", 3797 + "socket2", 2449 3798 "tokio-macros", 3799 + "windows-sys 0.61.2", 2450 3800 ] 2451 3801 2452 3802 [[package]] ··· 2461 3811 ] 2462 3812 2463 3813 [[package]] 3814 + name = "tokio-rustls" 3815 + version = "0.26.4" 3816 + source = "registry+https://github.com/rust-lang/crates.io-index" 3817 + checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 3818 + dependencies = [ 3819 + "rustls", 3820 + "tokio", 3821 + ] 3822 + 3823 + [[package]] 3824 + name = "tokio-util" 3825 + version = "0.7.18" 3826 + source = "registry+https://github.com/rust-lang/crates.io-index" 3827 + checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" 3828 + dependencies = [ 3829 + "bytes", 3830 + "futures-core", 3831 + "futures-sink", 3832 + "pin-project-lite", 3833 + "tokio", 3834 + ] 3835 + 3836 + [[package]] 2464 3837 name = "toml" 2465 3838 version = "0.9.12+spec-1.1.0" 2466 3839 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2528 3901 "serde", 2529 3902 "serde_json", 2530 3903 "streaming-iterator", 2531 - "thiserror", 3904 + "thiserror 2.0.18", 2532 3905 "tokio", 2533 3906 "topiary-tree-sitter-facade", 2534 3907 "topiary-web-tree-sitter-sys", ··· 2569 3942 ] 2570 3943 2571 3944 [[package]] 3945 + name = "tower" 3946 + version = "0.5.3" 3947 + source = "registry+https://github.com/rust-lang/crates.io-index" 3948 + checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" 3949 + dependencies = [ 3950 + "futures-core", 3951 + "futures-util", 3952 + "pin-project-lite", 3953 + "sync_wrapper", 3954 + "tokio", 3955 + "tower-layer", 3956 + "tower-service", 3957 + ] 3958 + 3959 + [[package]] 3960 + name = "tower-http" 3961 + version = "0.6.11" 3962 + source = "registry+https://github.com/rust-lang/crates.io-index" 3963 + checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" 3964 + dependencies = [ 3965 + "bitflags", 3966 + "bytes", 3967 + "futures-util", 3968 + "http", 3969 + "http-body", 3970 + "pin-project-lite", 3971 + "tower", 3972 + "tower-layer", 3973 + "tower-service", 3974 + "url", 3975 + ] 3976 + 3977 + [[package]] 3978 + name = "tower-layer" 3979 + version = "0.3.3" 3980 + source = "registry+https://github.com/rust-lang/crates.io-index" 3981 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 3982 + 3983 + [[package]] 3984 + name = "tower-service" 3985 + version = "0.3.3" 3986 + source = "registry+https://github.com/rust-lang/crates.io-index" 3987 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 3988 + 3989 + [[package]] 3990 + name = "tracing" 3991 + version = "0.1.44" 3992 + source = "registry+https://github.com/rust-lang/crates.io-index" 3993 + checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" 3994 + dependencies = [ 3995 + "pin-project-lite", 3996 + "tracing-attributes", 3997 + "tracing-core", 3998 + ] 3999 + 4000 + [[package]] 4001 + name = "tracing-attributes" 4002 + version = "0.1.31" 4003 + source = "registry+https://github.com/rust-lang/crates.io-index" 4004 + checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" 4005 + dependencies = [ 4006 + "proc-macro2", 4007 + "quote", 4008 + "syn", 4009 + ] 4010 + 4011 + [[package]] 4012 + name = "tracing-core" 4013 + version = "0.1.36" 4014 + source = "registry+https://github.com/rust-lang/crates.io-index" 4015 + checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 4016 + dependencies = [ 4017 + "once_cell", 4018 + ] 4019 + 4020 + [[package]] 2572 4021 name = "tree-sitter" 2573 4022 version = "0.26.9" 2574 4023 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2600 4049 ] 2601 4050 2602 4051 [[package]] 4052 + name = "try-lock" 4053 + version = "0.2.5" 4054 + source = "registry+https://github.com/rust-lang/crates.io-index" 4055 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 4056 + 4057 + [[package]] 2603 4058 name = "typed-arena" 2604 4059 version = "2.0.2" 2605 4060 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2612 4067 checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" 2613 4068 2614 4069 [[package]] 4070 + name = "ulid" 4071 + version = "1.2.1" 4072 + source = "registry+https://github.com/rust-lang/crates.io-index" 4073 + checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" 4074 + dependencies = [ 4075 + "rand 0.9.4", 4076 + "web-time", 4077 + ] 4078 + 4079 + [[package]] 4080 + name = "unicase" 4081 + version = "2.9.0" 4082 + source = "registry+https://github.com/rust-lang/crates.io-index" 4083 + checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" 4084 + 4085 + [[package]] 2615 4086 name = "unicode-ident" 2616 4087 version = "1.0.24" 2617 4088 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2667 4138 version = "0.2.11" 2668 4139 source = "registry+https://github.com/rust-lang/crates.io-index" 2669 4140 checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" 4141 + 4142 + [[package]] 4143 + name = "unsigned-varint" 4144 + version = "0.8.0" 4145 + source = "registry+https://github.com/rust-lang/crates.io-index" 4146 + checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" 2670 4147 2671 4148 [[package]] 2672 4149 name = "untrusted" ··· 2703 4180 ] 2704 4181 2705 4182 [[package]] 4183 + name = "urlencoding" 4184 + version = "2.1.3" 4185 + source = "registry+https://github.com/rust-lang/crates.io-index" 4186 + checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 4187 + 4188 + [[package]] 2706 4189 name = "utf8_iter" 2707 4190 version = "1.0.4" 2708 4191 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2715 4198 checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 2716 4199 2717 4200 [[package]] 4201 + name = "uuid" 4202 + version = "1.23.2" 4203 + source = "registry+https://github.com/rust-lang/crates.io-index" 4204 + checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" 4205 + dependencies = [ 4206 + "getrandom 0.4.2", 4207 + "js-sys", 4208 + "wasm-bindgen", 4209 + ] 4210 + 4211 + [[package]] 2718 4212 name = "version_check" 2719 4213 version = "0.9.5" 2720 4214 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2740 4234 ] 2741 4235 2742 4236 [[package]] 4237 + name = "want" 4238 + version = "0.3.1" 4239 + source = "registry+https://github.com/rust-lang/crates.io-index" 4240 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 4241 + dependencies = [ 4242 + "try-lock", 4243 + ] 4244 + 4245 + [[package]] 2743 4246 name = "wasi" 2744 4247 version = "0.11.1+wasi-snapshot-preview1" 2745 4248 source = "registry+https://github.com/rust-lang/crates.io-index" 2746 4249 checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 4250 + 4251 + [[package]] 4252 + name = "wasip2" 4253 + version = "1.0.3+wasi-0.2.9" 4254 + source = "registry+https://github.com/rust-lang/crates.io-index" 4255 + checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" 4256 + dependencies = [ 4257 + "wit-bindgen 0.57.1", 4258 + ] 4259 + 4260 + [[package]] 4261 + name = "wasip3" 4262 + version = "0.4.0+wasi-0.3.0-rc-2026-01-06" 4263 + source = "registry+https://github.com/rust-lang/crates.io-index" 4264 + checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" 4265 + dependencies = [ 4266 + "wit-bindgen 0.51.0", 4267 + ] 2747 4268 2748 4269 [[package]] 2749 4270 name = "wasm-bindgen" ··· 2817 4338 ] 2818 4339 2819 4340 [[package]] 4341 + name = "wasm-encoder" 4342 + version = "0.244.0" 4343 + source = "registry+https://github.com/rust-lang/crates.io-index" 4344 + checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" 4345 + dependencies = [ 4346 + "leb128fmt", 4347 + "wasmparser", 4348 + ] 4349 + 4350 + [[package]] 4351 + name = "wasm-metadata" 4352 + version = "0.244.0" 4353 + source = "registry+https://github.com/rust-lang/crates.io-index" 4354 + checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" 4355 + dependencies = [ 4356 + "anyhow", 4357 + "indexmap", 4358 + "wasm-encoder", 4359 + "wasmparser", 4360 + ] 4361 + 4362 + [[package]] 4363 + name = "wasmparser" 4364 + version = "0.244.0" 4365 + source = "registry+https://github.com/rust-lang/crates.io-index" 4366 + checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" 4367 + dependencies = [ 4368 + "bitflags", 4369 + "hashbrown 0.15.5", 4370 + "indexmap", 4371 + "semver", 4372 + ] 4373 + 4374 + [[package]] 2820 4375 name = "web-sys" 2821 4376 version = "0.3.77" 2822 4377 source = "registry+https://github.com/rust-lang/crates.io-index" 2823 4378 checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 4379 + dependencies = [ 4380 + "js-sys", 4381 + "wasm-bindgen", 4382 + ] 4383 + 4384 + [[package]] 4385 + name = "web-time" 4386 + version = "1.1.0" 4387 + source = "registry+https://github.com/rust-lang/crates.io-index" 4388 + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2824 4389 dependencies = [ 2825 4390 "js-sys", 2826 4391 "wasm-bindgen", ··· 2855 4420 ] 2856 4421 2857 4422 [[package]] 4423 + name = "widestring" 4424 + version = "1.2.1" 4425 + source = "registry+https://github.com/rust-lang/crates.io-index" 4426 + checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" 4427 + 4428 + [[package]] 2858 4429 name = "winapi" 2859 4430 version = "0.3.9" 2860 4431 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2876 4447 source = "registry+https://github.com/rust-lang/crates.io-index" 2877 4448 checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 2878 4449 dependencies = [ 2879 - "windows-sys 0.52.0", 4450 + "windows-sys 0.61.2", 2880 4451 ] 2881 4452 2882 4453 [[package]] ··· 2892 4463 checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 2893 4464 2894 4465 [[package]] 4466 + name = "windows-registry" 4467 + version = "0.6.1" 4468 + source = "registry+https://github.com/rust-lang/crates.io-index" 4469 + checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" 4470 + dependencies = [ 4471 + "windows-link", 4472 + "windows-result", 4473 + "windows-strings", 4474 + ] 4475 + 4476 + [[package]] 4477 + name = "windows-result" 4478 + version = "0.4.1" 4479 + source = "registry+https://github.com/rust-lang/crates.io-index" 4480 + checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" 4481 + dependencies = [ 4482 + "windows-link", 4483 + ] 4484 + 4485 + [[package]] 4486 + name = "windows-strings" 4487 + version = "0.5.1" 4488 + source = "registry+https://github.com/rust-lang/crates.io-index" 4489 + checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" 4490 + dependencies = [ 4491 + "windows-link", 4492 + ] 4493 + 4494 + [[package]] 2895 4495 name = "windows-sys" 2896 4496 version = "0.52.0" 2897 4497 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2998 4598 checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" 2999 4599 3000 4600 [[package]] 4601 + name = "wit-bindgen" 4602 + version = "0.51.0" 4603 + source = "registry+https://github.com/rust-lang/crates.io-index" 4604 + checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" 4605 + dependencies = [ 4606 + "wit-bindgen-rust-macro", 4607 + ] 4608 + 4609 + [[package]] 4610 + name = "wit-bindgen" 4611 + version = "0.57.1" 4612 + source = "registry+https://github.com/rust-lang/crates.io-index" 4613 + checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" 4614 + 4615 + [[package]] 4616 + name = "wit-bindgen-core" 4617 + version = "0.51.0" 4618 + source = "registry+https://github.com/rust-lang/crates.io-index" 4619 + checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" 4620 + dependencies = [ 4621 + "anyhow", 4622 + "heck 0.5.0", 4623 + "wit-parser", 4624 + ] 4625 + 4626 + [[package]] 4627 + name = "wit-bindgen-rust" 4628 + version = "0.51.0" 4629 + source = "registry+https://github.com/rust-lang/crates.io-index" 4630 + checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" 4631 + dependencies = [ 4632 + "anyhow", 4633 + "heck 0.5.0", 4634 + "indexmap", 4635 + "prettyplease", 4636 + "syn", 4637 + "wasm-metadata", 4638 + "wit-bindgen-core", 4639 + "wit-component", 4640 + ] 4641 + 4642 + [[package]] 4643 + name = "wit-bindgen-rust-macro" 4644 + version = "0.51.0" 4645 + source = "registry+https://github.com/rust-lang/crates.io-index" 4646 + checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" 4647 + dependencies = [ 4648 + "anyhow", 4649 + "prettyplease", 4650 + "proc-macro2", 4651 + "quote", 4652 + "syn", 4653 + "wit-bindgen-core", 4654 + "wit-bindgen-rust", 4655 + ] 4656 + 4657 + [[package]] 4658 + name = "wit-component" 4659 + version = "0.244.0" 4660 + source = "registry+https://github.com/rust-lang/crates.io-index" 4661 + checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" 4662 + dependencies = [ 4663 + "anyhow", 4664 + "bitflags", 4665 + "indexmap", 4666 + "log", 4667 + "serde", 4668 + "serde_derive", 4669 + "serde_json", 4670 + "wasm-encoder", 4671 + "wasm-metadata", 4672 + "wasmparser", 4673 + "wit-parser", 4674 + ] 4675 + 4676 + [[package]] 4677 + name = "wit-parser" 4678 + version = "0.244.0" 4679 + source = "registry+https://github.com/rust-lang/crates.io-index" 4680 + checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" 4681 + dependencies = [ 4682 + "anyhow", 4683 + "id-arena", 4684 + "indexmap", 4685 + "log", 4686 + "semver", 4687 + "serde", 4688 + "serde_derive", 4689 + "serde_json", 4690 + "unicode-xid", 4691 + "wasmparser", 4692 + ] 4693 + 4694 + [[package]] 3001 4695 name = "writeable" 3002 4696 version = "0.6.3" 3003 4697 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3045 4739 "quote", 3046 4740 "syn", 3047 4741 "synstructure", 4742 + ] 4743 + 4744 + [[package]] 4745 + name = "zerocopy" 4746 + version = "0.8.50" 4747 + source = "registry+https://github.com/rust-lang/crates.io-index" 4748 + checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" 4749 + dependencies = [ 4750 + "zerocopy-derive", 4751 + ] 4752 + 4753 + [[package]] 4754 + name = "zerocopy-derive" 4755 + version = "0.8.50" 4756 + source = "registry+https://github.com/rust-lang/crates.io-index" 4757 + checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" 4758 + dependencies = [ 4759 + "proc-macro2", 4760 + "quote", 4761 + "syn", 3048 4762 ] 3049 4763 3050 4764 [[package]]
+5
native/mlang_http/Cargo.toml
··· 7 7 crate-type = ["staticlib"] 8 8 9 9 [dependencies] 10 + atproto-client = "0.14" 11 + atproto-identity = "0.14" 12 + atproto-record = "0.14" 10 13 nickel-lang-core = "0.17" 14 + reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 11 15 serde_json = "1" 16 + tokio = { version = "1", features = ["rt-multi-thread"] } 12 17 ureq = { version = "2.10", default-features = true }
+67 -7
native/mlang_http/src/lib.rs
··· 1 + use atproto_client::{HttpRecordResolver, RecordResolver}; 2 + use atproto_identity::resolve::{HickoryDnsResolver, InnerIdentityResolver, SharedIdentityResolver}; 3 + use atproto_record::aturi::ATURI; 1 4 use nickel_lang_core::deserialize; 2 5 use std::ffi::{CStr, CString}; 3 6 use std::io::Read; 4 7 use std::os::raw::c_char; 5 8 use std::ptr; 9 + use std::str::FromStr; 10 + use std::sync::Arc; 6 11 7 12 fn render_json_value(value: &serde_json::Value) -> Result<String, String> { 8 13 match value { ··· 13 18 Ok(i.to_string()) 14 19 } else if let Some(u) = n.as_u64() { 15 20 Ok(u.to_string()) 16 - } else if let Some(f) = n.as_f64() { 17 - if f.fract() == 0.0 { 18 - Ok(format!("{:.0}", f)) 19 - } else { 20 - Err(format!("non-integer Nickel number is not supported: {n}")) 21 - } 22 21 } else { 23 - Err(format!("non-integer Nickel number is not supported: {n}")) 22 + Ok(n.to_string()) 24 23 } 25 24 } 26 25 serde_json::Value::String(s) => serde_json::to_string(s) ··· 72 71 let value: serde_json::Value = 73 72 serde_json::from_str(source).map_err(|err| format!("{err}"))?; 74 73 render_json_value(&value) 74 + } 75 + 76 + fn aturi_to_data_string(source: &str) -> Result<String, String> { 77 + ATURI::from_str(source).map_err(|err| format!("{err}"))?; 78 + let runtime = tokio::runtime::Runtime::new() 79 + .map_err(|err| format!("failed to create Tokio runtime: {err}"))?; 80 + let value: serde_json::Value = runtime 81 + .block_on(async { 82 + let http_client = reqwest::Client::new(); 83 + let dns_resolver = Arc::new(HickoryDnsResolver::create_resolver(&[])); 84 + let identity_resolver = SharedIdentityResolver(Arc::new(InnerIdentityResolver { 85 + dns_resolver, 86 + http_client: http_client.clone(), 87 + plc_hostname: "plc.directory".to_owned(), 88 + })); 89 + let resolver = HttpRecordResolver::new(http_client, Arc::new(identity_resolver)); 90 + resolver.resolve(source).await 91 + }) 92 + .map_err(|err| format!("AT-URI lookup failed: {err}"))?; 93 + let body = 94 + serde_json::to_string(&value).map_err(|err| format!("failed to encode record: {err}"))?; 95 + json_to_data_string(&body) 75 96 } 76 97 77 98 fn alloc_c_string(s: String) -> *mut c_char { ··· 256 277 } 257 278 } 258 279 } 280 + 281 + #[no_mangle] 282 + pub extern "C" fn mlang_aturi_parse( 283 + source: *const c_char, 284 + out_body: *mut *mut c_char, 285 + out_error: *mut *mut c_char, 286 + ) -> i32 { 287 + if source.is_null() || out_body.is_null() || out_error.is_null() { 288 + return 0; 289 + } 290 + unsafe { 291 + *out_body = ptr::null_mut(); 292 + *out_error = ptr::null_mut(); 293 + } 294 + let source = unsafe { CStr::from_ptr(source) }; 295 + let source = match source.to_str() { 296 + Ok(source) => source, 297 + Err(err) => { 298 + unsafe { 299 + *out_error = alloc_c_string(format!("invalid AT-URI UTF-8: {err}")); 300 + } 301 + return 0; 302 + } 303 + }; 304 + match aturi_to_data_string(source) { 305 + Ok(rendered) => { 306 + unsafe { 307 + *out_body = alloc_c_string(rendered); 308 + } 309 + 1 310 + } 311 + Err(err) => { 312 + unsafe { 313 + *out_error = alloc_c_string(format!("AT-URI parse error: {err}")); 314 + } 315 + 0 316 + } 317 + } 318 + }
+9
native/mlang_http_ffi.c
··· 7 7 extern uint8_t mlang_nickel_eval(const char *source, char **out_body, char **out_error); 8 8 extern uint8_t mlang_nickel_eval_file(const char *path, char **out_body, char **out_error); 9 9 extern uint8_t mlang_json_eval(const char *source, char **out_body, char **out_error); 10 + extern uint8_t mlang_aturi_parse(const char *source, char **out_body, char **out_error); 10 11 extern void mlang_http_string_free(char *ptr); 11 12 extern lean_obj_res lean_mk_io_user_error(lean_obj_arg msg); 12 13 ··· 74 75 uint8_t ok = mlang_json_eval(lean_string_cstr(source), &body, &error); 75 76 return wrap_string_result(ok, body, error); 76 77 } 78 + 79 + LEAN_EXPORT lean_obj_res mlang_aturi_parse_string(b_lean_obj_arg source, lean_obj_arg world) { 80 + (void)world; 81 + char *body = NULL; 82 + char *error = NULL; 83 + uint8_t ok = mlang_aturi_parse(lean_string_cstr(source), &body, &error); 84 + return wrap_string_result(ok, body, error); 85 + }